题目:

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

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

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

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

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

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

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

代码:

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

502. IPO(最小堆+最大堆法 or 排序法)的更多相关文章

  1. Java 快速排序法 冒泡排序法 选择排序法 插入排序法

    1.快速排序的原理: 选择一个关键值作为基准值.比基准值小的都在左边序列(一般是无序的),比基准值大的都在右边(一般是无序的). 从后往前比较,用基准值和最后一个值比较,如果比基准值小的交换位置,如果 ...

  2. 《徐徐道来话Java》:PriorityQueue和最小堆

    在讲解PriorityQueue之前,需要先熟悉一个有序数据结构:最小堆. 最小堆是一种经过排序的完全二叉树,其中任一非终端节点数值均不大于其左孩子和右孩子节点的值. 可以得出结论,如果一棵二叉树满足 ...

  3. 基于python语言的经典排序法(冒泡法和选择排序法)

    前 每逢周末就遇雨期,闲暇之余,捣鼓了下python,心心念想学习,今天就在电脑上装了个2.7,学习了下经典算法,冒泡与选择排序法 第一次写关于python的文章,说的不当之处,多多指正,我积极改正 ...

  4. php排序介绍_冒泡排序_选择排序法_插入排序法_快速排序法

    这里我们介绍一些常用的排序方法,排序是一个程序员的基本功,所谓排序就是对一组数据,按照某个顺序排列的过程. 充效率看 冒泡排序法<选择排序法<插入排序法 排序分两大类: 内部排序法 交换式 ...

  5. JAVA基础学习之命令行方式、配置环境变量、进制的基本转换、排序法、JAVA文档生成等(1)

    1.命令行方式 dos命令行,常见的命令: dir:列出当前目录下的文件以及文件夹 md:创建目录 rd:删除目录 cd:进入指定目录 cd..:退回到上一级目录 cd/:退回到根目录 del:删除文 ...

  6. c++/java/python priority_que实现最大堆和最小堆

    #include<iostream>#include<vector>#include<math.h>#include<string>#include&l ...

  7. 最大堆 最小堆 解决TOPK问题

    堆:实质是一颗完全二叉树,最大堆的特点:父节点值均大于子节点:最小堆的父节点值均小于子节点: 一般使用连续内存存储堆内的值,因而可以根据当前节点的索引值推断子节点的索引值: 节点i的父节点为(i-1) ...

  8. Google 面试题:Java实现用最大堆和最小堆查找中位数 Find median with min heap and max heap in Java

    Google面试题 股市上一个股票的价格从开市开始是不停的变化的,需要开发一个系统,给定一个股票,它能实时显示从开市到当前时间的这个股票的价格的中位数(中值). SOLUTION 1: 1.维持两个h ...

  9. Black Box--[优先队列 、最大堆最小堆的应用]

    Description Our Black Box represents a primitive database. It can save an integer array and has a sp ...

随机推荐

  1. 安装Matlab R2017a 出现 “弹出DVD1 并插入DVD2” 解决办法超简单

    打开此电脑 找到驱动器虚拟镜像 右击选择弹出 点击另一个文件装载 点击确定即可

  2. hive内置方法一览

    引用 https://www.cnblogs.com/qingyunzong/p/8744593.html#_label0 官方文档 https://cwiki.apache.org/confluen ...

  3. Codeforces Round #340 (Div. 2) E XOR and Favorite Number 莫队板子

    #include<bits/stdc++.h> using namespace std; <<; struct node{ int l,r; int id; }q[N]; in ...

  4. vsto 学习

    Object到String类型转换的四种方式 通常object到string有四种方式:(假设有object obj) obj.ToString, Convert.ToString, (string) ...

  5. P5016 龙虎斗

    链接:P5016 ------------------------------------ 作为2019年的模拟,还是有必要写一些的 --------------------------------- ...

  6. H5测试方法

    一 功能测试 1 关注页面请求:请求数据是否正确,相应是否正确,是否有重复请求,造成流量浪费,响应速度变慢 2 关注application cache:cokkie值是否正确,清除cokkie后表现是 ...

  7. Dev-C++如何创建源代码模板?

    Dev-C++如何创建源代码模板? 预览图片 按下Ctrl+N或者点击新建源代码,就会自动出现这些代码了 以下是操作步骤 编写你的模板 这里有我的样例: #include<iostream> ...

  8. Can you answer these queries? HDU - 4027 有点坑

    #include<iostream> #include<cstring> #include<cstdio> #include<math.h> #incl ...

  9. 小白的java学习之路 “ 选择结构(一)”

    if选择结构: if选择结构是根据条件判断之后再做处理的一种语法结构. 1.if选择结构的语法: public class Demo{ public static void main(String[] ...

  10. 纪中5日T2 1565. 神秘山庄

    1565. 神秘山庄 (Standard IO) 原题 题目描述 翠亨村是一个神秘的山庄,并不是因为它孕育了伟人孙中山,更神秘的是山庄里有N只鬼.M只兔子,当然还有你.其中每秒钟: 1. 恰有两个生物 ...