写在前面
本专栏专注于分析与讲解【面试经典150】算法,两到三天更新一篇文章,欢迎催更……
专栏内容以分析题目为主,并附带一些对于本题涉及到的数据结构等内容进行回顾与总结,文章结构大致如下,部分内容会有增删:
- Tag:介绍本题牵涉到的知识点、数据结构;
- 题目来源:贴上题目的链接,方便大家查找题目并完成练习;
- 题目解读:复述题目(确保自己真的理解题目意思),并强调一些题目重点信息;
- 解题思路:介绍一些解题思路,每种解题思路包括思路讲解、实现代码以及复杂度分析;
- 知识回忆:针对今天介绍的题目中的重点内容、数据结构进行回顾总结。
Tag
【堆】【贪心】【优先队列】
题目来源
解题思路
方法一:贪心+优先队列
思路
使用贪心的思想解决本题,我们应该贪心地保证选择每次投资的项目获取的利润最大。
我们首先将项目按照所需资本从小到大进行排序,每次选择时,假设当前手中持有的资本为 w
,我们应该从所有投入资本小于等于 w
的项目中选择利润最大的项目 j
,然后此时我们更新手中持有的资本为 w+profits[j]
。就这样贪心的选择 k
次即可。
在从所有投入资本小于等于 w
的项目中选择利润最大的项目时,使用大顶堆,将所有能够投资的项目的利润全部压入到堆中,每次从堆中取出最大值,然后更新手中持有的资本,同时将待选的项目利润进入堆,不断重复上述操作。
需要注意的是,本题中的利润是纯利润,指的是已经扣除成本之后获得的利润,所以更新原始资本时直接加上对应的利润即可。
代码
class Solution {
public:
int findMaximizedCapital(int k, int w, vector<int>& profits, vector<int>& capital) {
int n = profits.size();
int idx = 0;
priority_queue<int, vector<int>, less<int>> pq;
vector<pair<int, int>> 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 (idx < n && arr[idx].first <= w) {
pq.push(arr[idx].second);
++idx;
}
if (!pq.empty()) {
w += pq.top();
pq.pop();
}
else {
break;
}
}
return w;
}
};
复杂度分析
时间复杂度:
O
(
(
n
+
k
)
l
o
g
n
)
O((n+k)logn)
O((n+k)logn),其中
n
n
n 是数组 profits
和 capital
的长度,k
表示最多的选择数目。我们需要
O
(
n
log
n
)
O(n \log n)
O(nlogn) 的时间复杂度来来创建和排序项目,往堆中添加元素的时间不超过
O
(
n
log
n
)
O(n \log n)
O(nlogn),每次从堆中取出最大值并更新资本的时间为
O
(
k
log
n
)
O(k \log n)
O(klogn),因此总的时间复杂度为
O
(
n
log
n
+
n
log
n
+
k
log
n
)
=
O
(
(
n
+
k
)
log
n
)
O(n \log n + n \log n + k \log n) = O((n + k) \log n)
O(nlogn+nlogn+klogn)=O((n+k)logn)。
空间复杂度: O ( n ) O(n) O(n)。空间复杂度主要取决于创建用于排序的数组和大根堆。
写在最后
如果您发现文章有任何错误或者对文章有任何疑问,欢迎私信博主或者在评论区指出 💬💬💬。
如果大家有更优的时间、空间复杂度的方法,欢迎评论区交流。
最后,感谢您的阅读,如果有所收获的话可以给我点一个 👍 哦。