502.IPO
假设 力扣(LeetCode)即将开始IPO 。为了以更高的价格将股票卖给风险投资公司,力扣 希望在 IPO 之前开展一些项目以增加其资本。 由于资源有限,它只能在 IPO 之前完成最多 k
个不同的项目。帮助 力扣 设计完成最多 k
个不同项目后得到最大总资本的方式。
给你 n
个项目。对于每个项目 i
,它都有一个纯利润 profits[i]
,和启动该项目需要的最小资本 capital[i]
。
最初,你的资本为 w
。当你完成一个项目时,你将获得纯利润,且利润将被添加到你的总资本中。
总而言之,从给定项目中选择最多 k
个不同项目的列表,以最大化最终资本 ,并输出最终可获得的最多资本。
答案保证在 32 位有符号整数范围内。
这道题的难度其实并不高,相较于一些middle的题做起来甚至也更简单一些。
首先看最多完成k个不同项目,初始资本为w,每个项目有所需要的资本capital[i]和可获得的利润profits[i]。
如果没有k个不同项目的限制,那么显然只需要每个项目所需要的资本小于等于当前所拥有的资本,这个项目就可执行。怎样获得最大的收益呢?当然是在这一次的选择中,选择利润最大的一个项目,贪心地进行下去,就可以获得总的最大利润。
加上k个项目的限制,只需要在上面的基础上限定选择次数为k。
具体的算法:
将资本和利润组合成一个项目,将所有的项目按照资本从小到大排列
使用优先队列,将每次选择的所有可进行的项目的利润(所需资本小于等于当前拥有的资本)放入优先队列q
如果优先队列q不空,取出第一个(最大利润)加上当前拥有的资本成为新的资本
如果q空则退出
重复上述操作,限定进行k次,即可获得k个项目的最大利润
class Solution {
public:
int findMaximizedCapital(int k, int w, vector<int>& profits, vector<int>& capital) {
priority_queue<int, vector<int>, less<>> q; // 项目的利润由大到小排列的优先队列
// 将项目按所需资本从小到大排列 一个项目要组合成 资本和利润
vector<pair<int, int>> projects;
int n = profits.size(); // 项目总数
for (int i = 0; i < n; ++i) {
projects.emplace_back(capital[i], profits[i]);
}
sort(projects.begin(), projects.end()); // 所有项目处理完毕
int j = 0;
for (int i = 0; i < k; ++i) { // 只能进行k个项目
for (; j < n && projects[j].first <= w; ++j) { // 对所有的项目
// 如果这个项目的资本小于等于当前资本
q.push(projects[j].second); // 将这个项目的利润放入优先队列
}
if (!q.empty()) { // 如果这个优先队列还不空
w += q.top(); // 更新资本
q.pop(); // 去掉队首项目的利润
} else {
break;
}
}
return w;
}
};