如果初始资本 w \ge \max(\textit{capital}),我们直接返回利润中的 k 个最大元素的和即可。
当前的题目中限定了可以选择的次数最多为 k 次,这就意味着我们应该贪心地保证选择每次投资的项目获取的利润最大,这样就能保持选择 k 次后获取的利润最大。
我们首先将项目按照所需资本的从小到大进行排序,每次进行选择时,假设当前手中持有的资本为 w,我们应该从所有投入资本小于等于 w 的项目中选择利润最大的项目 j,然后此时我们更新手中持有的资本为 w + \textit{profits}[j],同时再从所有花费资本小于等于 w + \textit{profits}[j] 的项目中选择,我们按照上述规则不断选择 k 次即可。
classSolution { public: intfindMaximizedCapital(int k, int w, vector<int>& profits, vector<int>& capital){ int n = profits.size(); int curr = 0; priority_queue<int, vector<int>, less<int>> pq; vector<pii> arr;
for (int i = 0; i < n; ++i) { arr.push_back({capital[i], profits[i]}); } sort(arr.begin(), arr.end()); for (int i = 0; i < k; ++i) { while (curr < n && arr[curr].first <= w) { pq.push(arr[curr].second); curr++; } if (!pq.empty()) { w += pq.top(); pq.pop(); } else { break; } }
classSolution: deffindMaximizedCapital(self, k: int, w: int, profits: List[int], capital: List[int]) -> int: if w >= max(capital): return w + sum(nlargest(k, profits))
n = len(profits) curr = 0 arr = [(capital[i], profits[i]) for i inrange(n)] arr.sort(key = lambda x : x[0]) pq = [] for _ inrange(k): while curr < n and arr[curr][0] <= w: heappush(pq, -arr[curr][1]) curr += 1
funcfindMaximizedCapital(k, w int, profits, capital []int)int { n := len(profits) type pair struct{ c, p int } arr := make([]pair, n) for i, p := range profits { arr[i] = pair{capital[i], p} } sort.Slice(arr, func(i, j int)bool { return arr[i].c < arr[j].c })
h := &hp{} for cur := 0; k > 0; k-- { for cur < n && arr[cur].c <= w { heap.Push(h, arr[cur].p) cur++ } if h.Len() == 0 { break } w += heap.Pop(h).(int) } 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 interface{}) { h.IntSlice = append(h.IntSlice, v.(int)) } func(h *hp) Pop() interface{} { a := h.IntSlice; v := a[len(a)-1]; h.IntSlice = a[:len(a)-1]; return v }
复杂度分析
时间复杂度:O((n + k) \log n),其中 n 是数组 profits 和 capital 的长度,k 表示最多的选择数目。我们需要 O(n \log n) 的时间复杂度来来创建和排序项目,往堆中添加元素的时间不超过 O(n \log n),每次从堆中取出最大值并更新资本的时间为 O(k \log n),因此总的时间复杂度为 O(n \log n + n \log n + k \log n) = O((n + k) \log n)。
空间复杂度:O(n),其中 n 是数组 profits 和 capital 的长度。空间复杂度主要取决于创建用于排序的数组和大根堆。