当前位置:   article > 正文

贪心算法总结(2)

贪心算法总结(2)

一、买卖股票的最佳时机

. - 力扣(LeetCode)

  1. class Solution {
  2. public:
  3. int maxProfit(vector<int>& prices)
  4. {
  5. int mini=INT_MAX;
  6. int ret=0;
  7. for(int&price:prices)
  8. {
  9. //遍历的时候,我们随时去更新最小的值,然后让每一位数都来-最小值 更新利润,这里不能直接用最大值
  10. //因为最大值可能在最小值的左边
  11. ret=max(ret,price-mini);
  12. mini=min(price,mini);
  13. }
  14. return ret;
  15. }
  16. };

二、买卖股票的最佳时机II 

. - 力扣(LeetCode)

解法1:双指针(重点掌握)

  1. class Solution {
  2. public:
  3. int maxProfit(vector<int>& p) {
  4. //只要是正收益 就交易 //双指针+贪心
  5. int ret=0,n=p.size();
  6. for(int i=0,j=0;i<n;)
  7. {
  8. while(j+1<n&&p[j+1]>p[j]) ++j;
  9. ret+=p[j]-p[i];
  10. ++j,i=j;
  11. }
  12. return ret;
  13. }
  14. };

解法2:拆分交易

  1. class Solution {
  2. public:
  3. int maxProfit(vector<int>& p) {
  4. //拆分交易
  5. int ret=0,n=p.size();
  6. for(int i=1;i<n;++i)
  7. if(p[i]>p[i-1]) ret+=p[i]-p[i-1];
  8. return ret;
  9. }
  10. };

 解法3:动态规划

  1. class Solution {
  2. public:
  3. int maxProfit(vector<int>& prices)
  4. {
  5. //有两种状态,第i天结束处于买入状态(手上有股票,可卖) 第i天结束后处于交易状态(手上没有股票,可以买
  6. int n=prices.size();
  7. //创建两个dp表
  8. vector<int> f(n);//第i天结束后处于买入状态
  9. //情况1,前一天处于买入状态,啥也没干,还是处于买入状态f[i]=f[i-1]
  10. //情况2,前一天卖过,然后今天刚买 f[i]=g[i-1]-prices[i]
  11. auto g=f;//第i天结束后处于交易状态
  12. //情况1,前一天还是可交易状态,啥也没干 g[i]=g[i-1]
  13. //情况2.前一天处于买入状态,今天刚卖出一只股票,外加手续费 g[i]=f[i-1]+prices[i]-fee
  14. //初始化,
  15. f[0]=-prices[0];
  16. for(int i=1;i<n;++i)
  17. {
  18. f[i]=max(f[i-1],g[i-1]-prices[i]);
  19. g[i]=max(g[i-1],f[i-1]+prices[i]);
  20. }
  21. return g[n-1];
  22. }
  23. };

三、K次取反后的最大化数组和

. - 力扣(LeetCode)

  1. class Solution {
  2. public:
  3. int largestSumAfterKNegations(vector<int>& nums, int k) {
  4. //分类讨论 m表示负数的个数
  5. //当m<=k 把前k大的负数都变成正数即可
  6. //m>k 时 先把所有的负数变成正数,然后看看k是奇数还是偶数
  7. //如果是偶数,直接返回总和,如果是奇数,还需要挑选最小的那个数进行取反
  8. int m=0,n=nums.size();
  9. for(auto e:nums) if(e<0) ++m;
  10. //开始进行分类讨论
  11. int ret=0;
  12. if(m>=k)
  13. {
  14. sort(nums.begin(),nums.end());
  15. for(int i=0;i<k;++i) ret+=-nums[i];
  16. for(int i=k;i<n;++i) ret+=nums[i];
  17. }
  18. else
  19. {
  20. int mini=INT_MAX;
  21. for(auto e:nums)
  22. {
  23. ret+=abs(e);
  24. mini=min(mini,abs(e));
  25. }
  26. if((k-m)%2) ret-=2*mini;
  27. }
  28. return ret;
  29. }
  30. };

四、按身高排序(下标数组排序)

. - 力扣(LeetCode)

解法2:哈希存下标映射

  1. class Solution {
  2. public:
  3. vector<string> sortPeople(vector<string>& names, vector<int>& h) {
  4. //解法1 创建一个新的二元数组,将身高和名字绑定,然后按照身高排序,再提取回来
  5. int n=names.size();
  6. map<int,string,greater<int>> hash;
  7. for(int i=0;i<n;++i) hash[h[i]]=names[i];
  8. //然后提取出来
  9. vector<string> ret;
  10. ret.reserve(n);
  11. for(auto kv:hash) ret.emplace_back(kv.second);
  12. return ret;
  13. }
  14. };

解法3:对下标排序(重要技巧)

  1. class Solution {
  2. public:
  3. vector<string> sortPeople(vector<string>& names, vector<int>& h) {
  4. //解法2 创建一个下标数组 对下标数组进行排序 然后找到原数组的信息
  5. int n=names.size();
  6. vector<int> index(n);
  7. for(int i=0;i<n;++i) index[i]=i;
  8. sort(index.begin(),index.end(),[&h](int i,int j){
  9. return h[i]>h[j];
  10. });
  11. vector<string> ret(n);
  12. for(int i=0;i<n;++i)
  13. ret[i]=names[index[i]];
  14. return ret;
  15. }
  16. };

五、优势洗牌(田忌赛马策略)

. - 力扣(LeetCode)

  1. class Solution {
  2. public:
  3. //如果比得过,就比,如果比不过 就干掉最强的那个
  4. vector<int> advantageCount(vector<int>& nums1, vector<int>& nums2) {
  5. //对nums1进行升序排序 对nums2进行下标的排序
  6. int n=nums1.size();
  7. sort(nums1.begin(),nums1.end());
  8. vector<int> index(n);
  9. iota(index.begin(), index.end(),0); //用val的连续++初始化
  10. sort(index.begin(),index.end(),[&nums2](const int&i,const int&j){
  11. return nums2[i]<nums2[j];
  12. });
  13. //然后进行赛马 //用nums2存储最后的结果
  14. int left=0,right=n-1;
  15. for(auto&x:nums1)
  16. if(x>nums2[index[left]]) nums2[index[left++]]=x; //如果我比你大 我就超越你
  17. else nums2[index[right--]]=x;
  18. return nums2;
  19. //交换论证法 更经常用的原因是 最优解可能是有多个的,所以我们可以把最优解调整成贪心解
  20. }
  21. };

六、分发饼干

. - 力扣(LeetCode)

  1. class Solution {
  2. public:
  3. int findContentChildren(vector<int>& g, vector<int>& s) {
  4. //先排序 满足的直接喂 不满足的就看看下一个孩子
  5. sort(g.begin(),g.end());
  6. sort(s.begin(),s.end());
  7. //双指针
  8. int ret=0,n1=g.size(),n2=s.size();
  9. for(int i=0,j=0;i<n1&&j<n2;++i,++j)
  10. {
  11. //找饼干
  12. while(j<n2&&s[j]<g[i]) ++j;
  13. if(j<n2) ++ret;
  14. }
  15. return ret;
  16. }
  17. };

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/笔触狂放9/article/detail/990479
推荐阅读
相关标签
  

闽ICP备14008679号