1. 题目描述
假设 力扣(LeetCode
)即将开始 IPO
。为了以更高的价格将股票卖给风险投资公司,力扣 希望在 IPO
之前开展一些项目以增加其资本。 由于资源有限,它只能在 IPO
之前完成最多 k
个不同的项目。帮助 力扣 设计完成最多 k
个不同项目后得到最大总资本的方式。
给你 n
个项目。对于每个项目 i ,它都有一个纯利润 profits[i]
,和启动该项目需要的最小资本 capital[i]
。
最初,你的资本为 w
。当你完成一个项目时,你将获得纯利润,且利润将被添加到你的总资本中。
总而言之,从给定项目中选择 最多 k
个不同项目的列表,以 最大化最终资本 ,并输出最终可获得的最多资本。
答案保证在 32
位有符号整数范围内。
示例 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。
示例 2:
输入:k = 3, w = 0, profits = [1,2,3], capital = [0,1,2]
输出:6
提示:
1 <= k <= 1 0 5 10^5 105
0 <= w <= 1 0 9 10^9 109
n == profits.length
n == capital.length
1 <= n <= 1 0 5 10^5 105
0 <= profits[i] <= 1 0 4 10^4 104
0 <= capital[i] <= 1 0 9 10^9 109
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/ipo
2. 解答
2.1 朴素求解
也就是直接提取题意,按照题意,需要进行k轮,每次我们去寻找满足capital[i]<=w 且 profits[i]最大的那个下标,也就是我们下一轮的目标。代码如下:
class Solution {
public int findMaximizedCapital(int k, int w, int[] profits, int[] capital) {
boolean[] used = new boolean[capital.length];
int sum = w;
for (int i = 0; i < k; i++) { // choose k step
int idx = getMaxProfitIdx(capital, profits, used, w);
if(idx == -1) return sum;
used[idx] = true;
w += profits[idx];
sum += profits[idx];
}
return sum;
}
// 获取可选择的最大利润
private int getMaxProfitIdx(int[] capital, int[] profits, boolean[] used, int w) {
int maxProfits = Integer.MIN_VALUE;
int idx = -1;
for (int i = 0; i < capital.length; i++) {
if(used[i] || (idx != -1 && capital[i] == capital[idx] && profits[i] == profits[idx])) continue;
if(capital[i] <= w && maxProfits < profits[i]){
maxProfits = profits[i];
idx = i;
}
}
return idx;
}
}
不出意外超时了。
其实可以预料,因为数组的长度为 1 0 5 10^5 105,那么对于一个时间复杂度为 O ( n 2 ) O(n^2) O(n2)的算法来说是通不过的。这一点需要强化记忆。
2.2 堆排序
因为我们每次是找寻满足条件的最大利润,故而可以使用堆排序来做。
class Solution {
public int findMaximizedCapital(int k, int w, int[] profits, int[] capital) {
int len = capital.length;
boolean[] used = new boolean[len];
int[][] pairs = new int[len][2];
for (int i = 0; i < len; i++) {
pairs[i][0] = profits[i];
pairs[i][1] = capital[i];
}
Arrays.sort(pairs, (o1, o2) -> o1[1] - o2[1]);
PriorityQueue<Integer> queue = new PriorityQueue<>((o1, o2) -> o2 - o1);
int curIdx = 0;
for (int i = 0; i < k; i++) { // choose k step
while(curIdx < len && pairs[curIdx][1] <= w){
queue.add(pairs[curIdx][0]);
curIdx++;
}
if(!queue.isEmpty()){
w += queue.poll();
}else break;
}
return w;
}
}
Thanks