Question
Suppose LeetCode will start its IPO soon. In order to sell a good price of its shares to Venture Capital, LeetCode would like to work on some projects to increase its capital before the IPO. Since it has limited resources, it can only finish at most k
distinct projects before the IPO. Help LeetCode design the best way to maximize its total capital after finishing at most k
distinct projects.
You are given n
projects where the ith
project has a pure profit profits[i]
and a minimum capital of capital[i]
is needed to start it.
Initially, you have w
capital. When you finish a project, you will obtain its pure profit and the profit will be added to your total capital.
Pick a list of at most k
distinct projects from given projects to maximize your final capital, and return the final maximized capital.
The answer is guaranteed to fit in a 32-bit signed integer.
Example 1:
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 =
Brief Solution Summary
The problem is to find the k most valuable projects that maximize profit while minimizing capital investment before an IPO. At each stage, we want to choose the project that costs the least but yields the most profit. To achieve this, we start by creating a min heap with all the capital values. This brings the least capital-intensive projects to the top. We need to ensure that, at each iteration , the projects we choose meet the available capital. We add all the items that meet our capital requirements to a max heap — called the profit heap — where we use the profit to determine the order. At each iteration, the profit heap will contain feasible projects at the capital level, and we will select the most profitable one. We add that project to our available capital. If, at any time, we have projects that exceed our available capital requirement, we break the loop.
Leetcode
Implementation
- To find the project with the lowest value available to us, we add all the capital values into a min heap.
- Finding the 'k' best projects—We iterate 'k' times and select the best project to be executed at each iteration. We prioritize projects with the best capital-to-profit ratio.
- We pop all the projects that can be done with the available capital at that iterations.
- When popping from a capitalHeap (min heap), we select projects that require the least amount of capital, they fit within our capital constraints (based on the while loop)
- After extracting the capital of a project, we simultaneously add the corresponding profit value to our profit heap (max heap) by matching the index of the project that was popped from our capital heap. Thus, the profit heap will contain all profit values of the projects that can be done at that iteration with the available capital.
- We only need to choose the project with the highest profit. Using a max heap, we can easily achieve this by popping the top element.
- If we cannot add any projects to the profit heap at any point due to a lack of funds, we immediately break the loop.
capitalHeap = []
profitHeap = []
minCapitalHeap = [(capital[i],i) for i in range(len(capital))]
heapify(minCapitalHeap)
for _ in range(k):
while capitalHeap and capitalHeap[0][0] <= availableCapital:
capital, i = heappop(capitalHeap)
heappush(profitHeap, (-profits[i], i))
The remaining projects that meet the capital requirements will still be inside the min heap, waiting to be popped out at the next iteration.
availableCapital += -heappop(profitHeap)[0]
if not profitHeap:
break
Code
from heapq import *
class Solution:
def findMaximizedCapital(self, k: int, w: int, profits: List[int], capital: List[int]) -> int:
capitalHeap = []
profitHeap = []
capitalHeap = [(capital[i],i) for i in range(len(capital))]
heapify(capitalHeap)
# Finding 'k' best projects
availableCapital = w
for _ in range(k):
while capitalHeap and capitalHeap[0][0] <= availableCapital:
capital, i = heappop(capitalHeap)
heappush(profitHeap, (-profits[i], i))
if not profitHeap:
break
# Add the profit from project with the maximum profit
availableCapital += -heappop(profitHeap)[0]
return availableCapital
Complexities
Time O(NlogN)
Space O(n)
Why not use O(KlogN)
since we will only be popping k times from the profit heap?
The reason it is O(NlogN)
is due to the cost incurred while switching from the capital heap to the profit heap. We might have to pop and push N times at most.
k = 1
w = 1
profits =[1,1,1,1,1,1,1,1,1]
capital =[1,1,1,1,1,1,1,1,1]
while capitalHeap and capitalHeap[0][0] <= availableCapital:
capital, i = heappop(capitalHeap) # pop
heappush(profitHeap, (-profits[i], i)) # push