ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

502. IPO(最小堆+最大堆法 or 排序法)

2020-02-21 23:53:35  阅读:421  来源: 互联网

标签:Node 资本 堆法 int IPO 最小 Capital 502 Profits


题目:

链接:https://leetcode-cn.com/problems/ipo/submissions/

 

假设 力扣(LeetCode)即将开始其 IPO。为了以更高的价格将股票卖给风险投资公司,力扣 希望在 IPO 之前开展一些项目以增加其资本。 由于资源有限,它只能在 IPO 之前完成最多 k 个不同的项目。帮助 力扣 设计完成最多 k 个不同项目后得到最大总资本的方式。

给定若干个项目。对于每个项目 i,它都有一个纯利润 Pi,并且需要最小的资本 Ci 来启动相应的项目。最初,你有 W 资本。当你完成一个项目时,你将获得纯利润,且利润将被添加到你的总资本中。

总而言之,从给定项目中选择最多 k 个不同项目的列表,以最大化最终资本,并输出最终可获得的最多资本。

示例 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。
 

注意:

假设所有输入数字都是非负整数。
表示利润和资本的数组的长度不超过 50000。
答案保证在 32 位有符号整数范围内。

 

分析:

吃了没文化的亏,题目的实际意思是每次投资需要花费的资本实际上不花费。啥意思呢,就是我有10块钱,我想买个15块钱的东西,不行,不让买。如果买5块的东西,可以倒手挣20块钱。可以,直接送你了,不要钱,然后我就有10+20=30块钱了。。。并不需要你花那5块钱买它再卖。。。

 

方法1---最小堆+最大堆:

先声明这是题解看来的,我是别的方法做的。

每次想投资的话,我们需要选一个资本不超过我们现有资金的,而对于利润实际上没有什么要求。毕竟利润是白送给我们,资本也不扣钱,所以只要我们现有的钱够的前提下,就应该选一个利润最大的来投资! 然后我们维护一个最小堆,一个最大堆,其中最小堆存储还没买的所有股票,最大堆存储可以买的所有股票。

一开始最小堆是包含所有数据的,最大堆为空。


1.如果最小堆堆顶不超过我们现在的资金W,那么就可以考虑进行投资。

则我们把最小堆的堆顶pop掉,并加入最大堆。

2.接下来重复以上步骤,直到最小堆堆顶的资本超过当前资金。

3.这时候最大堆中的股票都是可以投资的,堆顶是利润最大的,这正是我们想要的,所有直接pop,完成一笔投资!

 

继续重复以上步骤K-1次,一共完成K笔交易。或者股票都买完了还不够K次,直接退出就好。


 

代码(懒得写了。。评论区粘一个)链接在此:https://leetcode-cn.com/problems/ipo/comments/209459

 

 1 class Node{
 2 public:
 3     Node(){}
 4     Node(int c, int p) : cost(c), profit(p){}
 5     int cost; 
 6     int profit;
 7 };
 8 // 优先队列的比较器 按照花费从小到大排序
 9 struct minCompare{
10     bool operator()(Node n1, Node n2){
11         return n1.cost > n2.cost;
12     }
13 };
14 // 优先队列的比较器 按照利润从大到小排序
15 struct maxCompare{
16     bool operator()(Node n1, Node n2){
17         return n1.profit < n2.profit;
18     }
19 };
20 class Solution {
21 public:
22     int findMaximizedCapital(int k, int W, vector<int>& Profits, vector<int>& Capital) {
23     // 全部构造节点
24     vector<Node> vec;
25     for(int i =  0; i < Profits.size(); i++){
26         vec.push_back(Node(Capital[i], Profits[i]));
27     }        
28     // 按照花费 从小到大的优先队列
29     priority_queue<Node, vector<Node>, minCompare> minCost;
30     // 按照利润 从大到小的优先队列
31     priority_queue<Node, vector<Node>, maxCompare> maxPro;
32     // 全部加入到小根堆中
33     for(int i = 0; i < vec.size(); i++){
34         minCost.push(vec[i]);
35     }
36     for(int i = 0; i < k; i++){
37         // 把当前能做的放入大根堆
38         while(!minCost.empty() && minCost.top().cost <= W){
39             maxPro.push(minCost.top());
40             minCost.pop();
41         }
42         // 没得做了
43         if(maxPro.empty()){
44             return W;
45         }
46         // 求当前profit
47         W += maxPro.top().profit;
48         maxPro.pop();
49     }
50     return W;
51 }
52 };

 

 

 

 

方法2---直接硬排序,线性查找法(误??):

 

我自己的方法,感觉复杂度是O(N^2),不如方法1,但实际跑起来还挺快的,可能数据集都比较小吧。

先建立一个索引数组,0~n-1,其中每个元素都指示题目两数组的某只股票。

然后对其排序,排序原则是利润大在前,利润相等则要求资本小的在前。

之后每次从头查找第一个可以投资的股票,投资之,弃之,再重复,直到K次或者数组空完事儿!

实际复杂度最大是O(n^2),但只有最后一组数据特别大,单独判断一下,最后时间还比方法1快不少。。

代码:

 1 class Solution {
 2 public:
 3     int findMaximizedCapital(int k, int W, vector<int>& Profits, vector<int>& Capital) {
 4         if(*max_element(Capital.begin(),Capital.end())<=W){
 5             sort(Profits.begin(),Profits.end());
 6             for(int i=Profits.size()-1;i>=max(0,int(Profits.size())-k);--i){W+=Profits[i];}
 7             return W;
 8         }
 9         auto cmp=[&](const int& x,const int& y){return Profits[x]>Profits[y] or Profits[x]==Profits[y] and Capital[x]<Capital[y];};
10         int n=Profits.size();
11         vector<int> nums(n);
12         for(int i=0;i<n;++i){nums[i]=i;}
13         sort(nums.begin(),nums.end(),cmp);
14         int cnt=0,cur_money=W;
15         auto iter=find_if(nums.begin(),nums.end(),[&](int x){return Capital[x]<=cur_money;});
16         while(cnt<k and iter!=nums.end()){
17             cur_money+=Profits[*iter];
18             Capital[*iter]=INT_MAX;//做记录
19             ++cnt;
20             iter=find_if(nums.begin(),nums.end(),[&](int x){return Capital[x]<=cur_money;});
21         }
22         return cur_money;
23     }
24 };

 

标签:Node,资本,堆法,int,IPO,最小,Capital,502,Profits
来源: https://www.cnblogs.com/FdWzy/p/12343780.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有