1. IPO
(1)暴搜
class Solution {
public int findMaximizedCapital(int k, int w, int[] profits, int[] capital) {
//暴力, 每次找利润最大时都要遍历一次
boolean []use = new boolean[profits.length];
int i = 0;
while (i < k) {
// 寻找最大利润
int maxIndex = -1;
for (int j = 0; j < profits.length; j++) {
if (use[j] == false && capital[j] <= w) {
if (maxIndex == -1) {
maxIndex = j;
}
else if (profits[j] > profits[maxIndex]) {
maxIndex = j;
}
}
}
if (maxIndex == -1) {
break;
}
// 投资
use[maxIndex] = true;
i ++;
w += profits[maxIndex];
}
return w;
}
}
(2)贪心 + 优先队列
每完成一个任务都会使得总资金 w 增加或不变。因此对于所选的第 i 个任务而言,应该在所有未被选择且启动资金不超过 w 的所有任务里面选利润最大的。
每次决策前,将启动资金不超过当前总资金的任务加入集合,再在里面取利润最大的任务
- 取最大的过程可以使用优先队列(根据利润排序的大根堆),而将启动资金不超过当前总资金的任务加入集合的操作,可以利用总资金在整个处理过程递增,而先对所有任务进行预处理排序来实现。
具体步骤
-
1.根据 profits 和 capital 预处理出总的任务集合二元组,并根据「启动资金」进行升序排序;
-
2.每次决策前,将所有的启动资金不超过 w 的任务加入优先队列(根据利润排序的大根堆),然后从优先队列(根据利润排序的大根堆),将利润累加到 w;
-
3.循环步骤 2,直到达到 k 个任务,或者队列为空(当前资金不足以选任何任务)。
-
时间复杂度:O(nlogn),空间复杂度:O(n)
class Solution {
public int findMaximizedCapital(int k, int w, int[] profits, int[] capital) {
int n = profits.length;
List<int []> list = new ArrayList<>();
//将所有启动资金,利润 存入list中
for (int i = 0; i < n; i++) {
list.add(new int[] {capital[i], profits[i]});
}
//根据「启动资金」进行升序排序
Collections.sort(list, (a, b) -> a[0] - b[0]);
//构建优先队列,根据利润排序的大根堆
//每次决策前,将所有的启动资金不超过 w 的任务加入优先队列
PriorityQueue<Integer> q = new PriorityQueue<>((a, b) -> b - a);
//直到达到 k 个任务,或者队列为空(当前资金不足以选任何任务)
int i = 0;
while(k > 0) {
while (i < n && list.get(i)[0] <= w) {
q.add(list.get(i)[1]);
i++;
}
if (q.isEmpty())
break;
w += q.poll();
k--;
}
//返回最后的资本
return w;
}
}