[LeetCode解题报告] 502. IPO
题目描述
假设 LeetCode 即将开始其 IPO。为了以更高的价格将股票卖给风险投资公司,LeetCode希望在 IPO 之前开展一些项目以增加其资本。 由于资源有限,它只能在 IPO 之前完成最多 k 个不同的项目。帮助 LeetCode 设计完成最多 k 个不同项目后得到最大总资本的方式。
给定若干个项目。对于每个项目 i,它都有一个纯利润 Pi,并且需要最小的资本 Ci 来启动相应的项目。最初,你有 W 资本。当你完成一个项目时,你将获得纯利润,且利润将被添加到你的总资本中。
总而言之,从给定项目中选择最多 k 个不同项目的列表,以最大化最终资本,并输出最终可获得的最多资本。
示例 1:
输入: k=2, W=0, Profits=[1,2,3], Capital=[0,1,1].
输出: 4
解释:
由于你的初始资本为 0,你尽可以从 0 号项目开始。
在完成后,你将获得 1 的利润,你的总资本将变为 1。
此时你可以选择开始 1 号或 2 号项目。
由于你最多可以选择两个项目,所以你需要完成 2 号项目以获得最大的资本。
因此,输出最后最大化的资本,为 0 + 1 + 3 = 4。
注意:
- 假设所有输入数字都是非负整数。
- 表示利润和资本的数组的长度不超过 50000。
- 答案保证在 32 位有符号整数范围内。
算法
这题我选择用堆排序来做,具体流程如下:
目标:最大化当前持有的资本
- 将
启动资本
与获利
打包在一个节点中再进行排序.具体的排序为按照启动资本
从小到大排序,如果相等的启动资本
,则按照获利
从大到小排序 - 循环遍历打包排序好的数组:将
当前持有的资本
与目前遍历到的节点所需的启动资本
比较:- 如果
当前持有的资本
大于或等于节点所需的启动资本
:将该节点能获取的利润
插入堆中,并将堆调整维护为一个最大堆(这样能保证堆顶始终存放着能以持有的资本
获取的最大利润
) - 如果
当前持有的资本
小于节点所需的启动资本
,更不用说后面的那些节点了,停止遍历,将堆顶存放的值加到当前持有的资本
中,并将堆顶删除 当前持有的资本
已经发生变化,继续在数组从刚才的位置往后遍历,直到选择完给定的k个项目
- 如果
边界条件
- 如果一开始给定的
当前持有的资本
比数组中最前面的那个节点带有的启动资本都要小,也就是说以当前持有的资本
根本选择不了任何一个启动项目,直接返回当前持有的资本
- 如果给定的可选k个项目比总的项目还要多,那么k值要变成中的项目数。因为总共就这么多,不可能选出比总数还多的项目来。
代码
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
// 将启动资本与获利打包在一个节点上
struct Node
{
int _p, _c;
};
// 自定义的排序流程
bool cmp(const Node &a, const Node &b)
{
bool flag;
if (a._c < b._c)
flag = true;
else if(a._c > b._c)
flag = false;
else
flag = (a._p > b._p) ? true : false;
return flag;
}
class Solution {
public:
int findMaximizedCapital(int k, int W, vector<int>& Profits, vector<int>& Capital) {
int len = Profits.size();
Node pack[len];
// 将启动成本与收益打包在一起,之后排序
for(int i = 0; i < len; i++)
{
pack[i]._p = Profits[i];
pack[i]._c = Capital[i];
}
sort(pack, pack+len, cmp);
// 边界条件,如果连最小的项目的启动成本都比W要大,那一开始就没有什么项目可选
if (pack[0]._c > W)
return 0;
// 边界条件,如果可选项目k的个数大于给定的项目个数,k应该重新赋值
if (k > len)
k = len;
int maxSum = W, i = 0;
vector<int> max_heap;
//开始算法
while (k)
{
for (; i < len && pack[i]._c <= maxSum; i++)
{
// 插入堆的末尾,并且调整为最大堆
max_heap.push_back(pack[i]._p);
PercUP(max_heap);
}
// 因为此时堆顶就是目前利润最大的项目的利润值,将堆顶元素加到maxSum上去,并删除堆顶(与最后一个互换,然后继续调整最大堆)
maxSum += max_heap[0];
max_heap[0] = max_heap[max_heap.size()-1];
max_heap.pop_back();
PercDown(max_heap);
k--;
}
return maxSum;
}
void PercUP(vector<int> &max_heap)
{
/*** 本函数将插至末尾的数向上调整至合适的位置以维护一个最大堆 ***/
int child = max_heap.size() - 1;
int X = max_heap[child], father;
while (child != 0)
{
father = (child - 1) / 2;
if (max_heap[father] >= X)
break;
max_heap[child] = max_heap[father];
child = father;
}
max_heap[child] = X;
}
void PercDown(vector<int> &max_heap)
{
/*** 本函数将交换后的堆顶向下调整至合适的位置以维护一个最大堆 ***/
int len = max_heap.size();
if (len == 0)
return;
int father, child, X = max_heap[0];
for (father = 0; father * 2 + 1 < len; father = child)
{
child = father * 2 + 1;
if (child + 1 < len && max_heap[child] < max_heap[child+1])
child++;
if (X >= max_heap[child])
break;
max_heap[father] = max_heap[child];
}
max_heap[father] = X;
}
};
int main()
{
vector<int> profit = {1,2,3};
vector<int> capital = {0, 1, 1};
int k = 10, w = 0;
Solution s;
cout << "最大资本是:" << s.findMaximizedCapital(k, w, profit, capital) << endl;
return 0;
}
最后
这题直接使用STL中的优先队列更方便,堆调整的算法也更好。
[LeetCode解题报告] 502. IPO的更多相关文章
- LeetCode解题报告:Linked List Cycle && Linked List Cycle II
LeetCode解题报告:Linked List Cycle && Linked List Cycle II 1题目 Linked List Cycle Given a linked ...
- leetcode解题报告(2):Remove Duplicates from Sorted ArrayII
描述 Follow up for "Remove Duplicates": What if duplicates are allowed at most twice? For ex ...
- LeetCode 解题报告索引
最近在准备找工作的算法题,刷刷LeetCode,以下是我的解题报告索引,每一题几乎都有详细的说明,供各位码农参考.根据我自己做的进度持续更新中...... ...
- leetCode解题报告5道题(六)
题目一: Longest Substring Without Repeating Characters Given a string, find the length of the longest s ...
- LeetCode解题报告—— Longest Valid Parentheses
Given a string containing just the characters '(' and ')', find the length of the longest valid (wel ...
- LeetCode解题报告—— Search in Rotated Sorted Array & Search for a Range & Valid Sudoku
1. Search in Rotated Sorted Array Suppose an array sorted in ascending order is rotated(轮流,循环) at so ...
- LeetCode解题报告—— 2 Keys Keyboard & Longest Palindromic Substring & ZigZag Conversion
1. Longest Palindromic Substring Given a string s, find the longest palindromic substring in s. You ...
- LeetCode解题报告—— 1-bit and 2-bit Characters & 132 Pattern & 3Sum
1. 1-bit and 2-bit Characters We have two special characters. The first character can be represented ...
- LeetCode解题报告--2Sum, 3Sum, 4Sum, K Sum求和问题总结
前言: 这几天在做LeetCode 里面有2sum, 3sum(closest), 4sum等问题, 这类问题是典型的递归思路解题.该这类问题的关键在于,在进行求和求解前,要先排序Arrays.sor ...
随机推荐
- E: Sub-process /usr/bin/dpkg returned an error code
E: Sub-process /usr/bin/dpkg returned an error code (1)错误解决 在用apt-get安装软件时出现了类似于install-info: No dir ...
- 词向量之word2vec实践
首先感谢无私分享的各位大神,文中很多内容多有借鉴之处.本次将自己的实验过程记录,希望能帮助有需要的同学. 一.从下载数据开始 现在的中文语料库不是特别丰富,我在之前的文章中略有整理,有兴趣的可以看看. ...
- [uboot] (第二章)uboot流程——uboot-spl编译流程
http://blog.csdn.net/ooonebook/article/details/52949584 以下例子都以project X项目tiny210(s5pv210平台,armv7架构)为 ...
- Linux 第四天
1.文件搜索命令 1)locate 在文件资料库中查找文件(需要文件资料库中有,新建的文件查不到,需要手动更新,updatedb.查不到/tmp目录下的文件) 语法:locate 文件名 常用选项: ...
- Codeforces Round #546 (Div. 2) E 推公式 + 线段树
https://codeforces.com/contest/1136/problem/E 题意 给你一个有n个数字的a数组,一个有n-1个数字的k数组,两种操作: 1.将a[i]+x,假如a[i]+ ...
- httpd-vhosts.conf配置
<VirtualHost 127.0.0.1:80> ServerName zjm.appems.com DocumentRoot E:\qian\web <Directory &q ...
- zookeeper学习day01
1.zkAPI:(借助闭锁来实现) 1)创建闭锁对象 2)创建zk对象 3)连接zk客户端(连接成功执行countDown方法) 4)执行await方法(保证链接成功) 5)zk对象调用对 ...
- bash编程-sed
sed(Stream Editor)是Linux系统下的一个文本流编辑器,它将文本文件内容逐行读取到标准输出,并将此行内容写入模式空间(pattern space),然后按照给定的地址定界和命令处理匹 ...
- 在.NET Core中三种实现“可插拔”AOP编程方式(附源码)
一看标题肯定会联想到使用动态编织的方式实现AOP编程,不过这不是作者本文讨论的重点. 本文讨论另外三种在netcore中可实现的方式,Filter(过滤器,严格意义上它算是AOP方式),Dynamic ...
- CentOS 解决vim乱码问题
今天在服务器安装了任务调度工具(TaskCTL) 发现是乱码的,看了官方文档说的办法也没有处理成功,可能由于他们已经有一段时间没有维护这个版本了.(以前提供的免费版本) 后来发现CentOS的Vim的 ...