题目:
假设 力扣(LeetCode)即将开始其 IPO。为了以更高的价格将股票卖给风险投资公司,力扣 希望在 IPO 之前开展一些项目以增加其资本。 由于资源有限,它只能在 IPO 之前完成最多 k 个不同的项目。帮助 力扣 设计完成最多 k 个不同项目后得到最大总资本的方式。
给定若干个项目。对于每个项目 i,它都有一个纯利润 Pi,并且需要最小的资本 Ci 来启动相应的项目。最初,你有 W 资本。当你完成一个项目时,你将获得纯利润,且利润将被添加到你的总资本中。
总而言之,从给定项目中选择最多 k 个不同项目的列表,以最大化最终资本,并输出最终可获得的最多资本。
输入: k=2, W=0, Profits=[1,2,3], Capital=[0,1,1].
输出: 4
解释:由于你的初始资本为 0,你尽可以从 0 号项目开始。
在完成后,你将获得 1 的利润,你的总资本将变为 1。
此时你可以选择开始 1 号或 2 号项目。
由于你最多可以选择两个项目,所以你需要完成 2 号项目以获得最大的资本。
因此,输出最后最大化的资本,为 0 + 1 + 3 = 4.
这一题是典型的贪心算法,由于获得的是纯利润,那么每次都要获得最大利润,(在资本够的情况下)
详细的解释在代码的注释里
class Solution {
public:
int findMaximizedCapital(int k, int W, vector<int>& Profits, vector<int>& Capital) {
//这是典型的贪心算法,我按照在资本允许的情况下,
//首先在花费资本最少的情况下,取得利润最大,
//这里理解有误,首先是纯利润,只要资本够就行,不需要花费资本
//所以每次都投最大利润,在资本够的情况下
//这样接下来就有更多的资本,来获取更大的利润
//即每一次都获得最大利润
list<vector<int>> sum;
int i=0;
vector<int> temp(2);
for(auto it:Profits){
temp[0]=it;
temp[1]=Capital[i++];
sum.push_back(temp);
};
//按照利润降序排列
sum.sort(greater<vector<int>>());
while(k--)
{
auto node=sum.begin();
while(node!=sum.end()){
if(W>=(*node)[1]){
W+=(*node)[0];
sum.erase(node);
break;
}
else ++node;
}
}
return W;
}
};
时间复杂度,我计算的是:
首先变成一个2维vector需要O(n),排序需要O(nlgn);然后是删除,
假设最坏情况是每次都在最后一个节点删除,那么时间为;
所以总的时间为O(nlgn+n+nk-k(k+1)/2);
不过还有一种最坏情况就是,一次都没删除节点,那就是nk;
总的时间复杂度为O(nlgn+(n+1)k);
空间复杂度为O(n)
还有人用大顶堆和小顶堆做的,我感觉没我这个思路清晰;不过时间复杂度就不知道了