题目描述:
由于时间有限你只可以完成k个项目,你目前有资金W,完成每个项目可以净收益Profits[],每个项目需要投资 Capital[]。问最后的资金最多是多少?
Input: k=2, W=0, Profits=[1,2,3], Capital=[0,1,1].
Output: 4
Explanation: Since your initial capital is 0, you can only start the project indexed 0.After finishing it you will obtain profit 1 and your capital becomes 1.With capital 1, you can either start the project indexed 1 or the project indexed 2.
Since you can choose at most 2 projects, you need to finish the project indexed 2 to get the maximum capital.Therefore, output the final maximized capital, which is 0 + 1 + 3 = 4.
解题思路:
这道题目其实不难,使用贪心算法的思想,每次选取在资金范围内收益最高的项目即可。代码如下:
class Solution {
public:
int findMaximizedCapital(int k, int W, vector<int>& Profits, vector<int>& Capital) {
for (int i = 0; i < k; ++i) {
int maxProfit = -1, project = -1;
for (int j = 0; j < Capital.size(); ++j) {
if (Capital[j] <= W && Profits[j] > maxProfit) {
maxProfit = Profits[j];
project = j;
}
}
if (maxProfit != -1) {
W += maxProfit;
//用迭代器删除指定元素
std::vector<int>::iterator it = Profits.begin() + project;
Profits.erase(it);
std::vector<int>::iterator it2 = Capital.begin() + project;
Capital.erase(it2);
}
else {
break;
}
}
return W;
}
};
但是在LeetCode上运行最后会超时,原因是最后一个测试数据过大,并且初始资金就足够完成任一项目,所以用代码如下可以节省时间:
class Solution {
public:
int findMaximizedCapital(int k, int W, vector<int>& P, vector<int>& C) {
priority_queue<int> low; // P[i]'s within current W
multiset<pair<int, int>> high; // (C[i],P[i])'s' outside current W
for (int i = 0; i < P.size(); ++i) // initialize low and high
if (P[i] > 0)
if (C[i] <= W)
low.push(P[i]);
else high.emplace(C[i], P[i]);
while (k-- && low.size()) {
W += low.top(), low.pop(); // greedy to work on most profitable first
for (auto i = high.begin(); high.size() && i->first <= W; i = high.erase(i))
low.push(i->second);
}
return W;
}
};
while循环内部的for循环在这种测试数据下基本不会运行,所以大大提高了时间复杂度。