题目描述
假设 力扣(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 <= 105
0 <= w <= 109
n == profits.length
n == capital.length
1 <= n <= 105
0 <= profits[i] <= 104
0 <= capital[i] <= 109
解法
方法一:贪心 + 优先队列(双堆)
将每个项目放入优先队列 $q_1$ 中,按照启动资本从小到大排序。如果堆顶元素启动资本不超过当前已有的资金,则循环弹出,放入另一个优先队列 $q_2$ 中,按照纯利润从大到小排序。取出当前利润最大的项目,将其纯利润加入到当前资金中,重复上述操作 $k$ 次。
时间复杂度 $O(n\log n)$,空间复杂度 $O(n)$。其中 $n$ 为项目数。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 | class Solution:
def findMaximizedCapital(
self, k: int, w: int, profits: List[int], capital: List[int]
) -> int:
h1 = [(c, p) for c, p in zip(capital, profits)]
heapify(h1)
h2 = []
while k:
while h1 and h1[0][0] <= w:
heappush(h2, -heappop(h1)[1])
if not h2:
break
w -= heappop(h2)
k -= 1
return w
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 | class Solution {
public int findMaximizedCapital(int k, int w, int[] profits, int[] capital) {
int n = capital.length;
PriorityQueue<int[]> q1 = new PriorityQueue<>((a, b) -> a[0] - b[0]);
for (int i = 0; i < n; ++i) {
q1.offer(new int[] {capital[i], profits[i]});
}
PriorityQueue<Integer> q2 = new PriorityQueue<>((a, b) -> b - a);
while (k-- > 0) {
while (!q1.isEmpty() && q1.peek()[0] <= w) {
q2.offer(q1.poll()[1]);
}
if (q2.isEmpty()) {
break;
}
w += q2.poll();
}
return w;
}
}
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25 | using pii = pair<int, int>;
class Solution {
public:
int findMaximizedCapital(int k, int w, vector<int>& profits, vector<int>& capital) {
priority_queue<pii, vector<pii>, greater<pii>> q1;
int n = profits.size();
for (int i = 0; i < n; ++i) {
q1.push({capital[i], profits[i]});
}
priority_queue<int> q2;
while (k--) {
while (!q1.empty() && q1.top().first <= w) {
q2.push(q1.top().second);
q1.pop();
}
if (q2.empty()) {
break;
}
w += q2.top();
q2.pop();
}
return w;
}
};
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 | func findMaximizedCapital(k int, w int, profits []int, capital []int) int {
q1 := hp2{}
for i, c := range capital {
heap.Push(&q1, pair{c, profits[i]})
}
q2 := hp{}
for k > 0 {
for len(q1) > 0 && q1[0].c <= w {
heap.Push(&q2, heap.Pop(&q1).(pair).p)
}
if q2.Len() == 0 {
break
}
w += heap.Pop(&q2).(int)
k--
}
return w
}
type hp struct{ sort.IntSlice }
func (h hp) Less(i, j int) bool { return h.IntSlice[i] > h.IntSlice[j] }
func (h *hp) Push(v any) { h.IntSlice = append(h.IntSlice, v.(int)) }
func (h *hp) Pop() any {
a := h.IntSlice
v := a[len(a)-1]
h.IntSlice = a[:len(a)-1]
return v
}
type pair struct{ c, p int }
type hp2 []pair
func (h hp2) Len() int { return len(h) }
func (h hp2) Less(i, j int) bool { return h[i].c < h[j].c }
func (h hp2) Swap(i, j int) { h[i], h[j] = h[j], h[i] }
func (h *hp2) Push(v any) { *h = append(*h, v.(pair)) }
func (h *hp2) Pop() any { a := *h; v := a[len(a)-1]; *h = a[:len(a)-1]; return v }
|