day 31 贪心(1)

day31
代码随想录
2023.12.29

今天开始贪心之路!
贪心的本质很简单,就是选取每一阶段的局部最优,从而达到全局最优。听起来很简单,但是遇到题就不一样了,有的非常简单,简单到你没有意识到自己用了贪心,但有的很难,难到无从下手。

贪心算法一般分为如下四步:

  • 将问题分解为若干个子问题
  • 找出适合的贪心策略
  • 求解每一个子问题的最优解
  • 将局部最优解堆叠成全局最优解

当然,这是一个粗略的大致步骤,真正做题要灵活运用。

1. 455分发饼干
这道题就是比较典型的贪心的,局部最优的点在于,针对孩子需求,每次饼干找刚好满足的,也就是说对于g数组中的数,遍历中找s中满足且最小的值!每次遍历达到这种效果,整体遍历就是满足孩子数量最多的了,至于代码写法也有很多了,开始写的时候,还有点写不出来,就多写了一个bool函数,表示饼干是否已经分发给孩子了,

class Solution {
   
public:
    bool find(int num, vector<int>& s, vector<bool>& used){
   
        for(int i=0;i<s.size();i++){
   
            if((num<s[i] || num==s[i]) && used[i]==false){
   //找到满足条件的饼干,值满足且最小且未分发给孩子
                used[i] = true;
                return true;
            }
        }
        return false;
    }
    int findContentChildren(vector<int>& g, vector<int>& s) {
   
        int result = 0;
        vector<bool> used(s.size(), false);
        if(s.size()==0){
   
            return result;
        }
        sort(s.begin(), s.end());
        sort(g.begin(), g.end());
        for(int i=0;i<g.size();i++){
   
            if(find(g[i],s, used)){
   
                result++;
            }
        }
        return result;
    }
};

2. 376摆动序列
这道题,看蒙了,不会做,还要删除节点,剩余节点满足最大摇摆序列,数组删除都麻烦,难不成每次删除然后位置都动一动?看文字讲解后发现,只需要统计满足要求的峰值就行(最大或最小),而峰值判断就是一个点两边差值正负相反。问题实际情况可能有很多种,平坡,一直是上坡、下坡等等,这种情况怎么办,以为又要分别判断了,但最后发现,就算有这些情况,不用做处理啊,直接跳过就行了,我们要的只有坡峰,所以只需要在坡峰时做一些操作就行,首先肯定结果数++,最后就是这个前后差值,后差值并不是值得当前节点紧挨的后插值,而是上次满足坡峰要求是的前差值,到这个点就变成后差值了,因此这个后差值,只需要在满足坡峰要求时更新就好,仔细想想,这个操作也就是将刚才说的各种情况全部跳过去的意思

class Solution {
   
public:
    int wiggleMaxLength(vector<int>& nums) {
   
        if (nums.size() <= 1) return nums.size();
        int curDiff = 0; // 当前一对差值
        int preDiff = 0; // 前一对差值
        int result = 1;  // 记录峰值个数,序列默认序列最右边有一个峰值
        for (int i = 0; i < nums.size() - 1; i++) {
   
            curDiff = nums[i + 1] - nums[i];
            // 出现峰值
            if ((preDiff <= 0 && curDiff > 0) || (preDiff >= 0 && curDiff < 0)) {
   
                result++;
                preDiff = curDiff; // 注意这里,只在摆动变化的时候更新prediff
            }
        }
        return result;
    }
};

3. 53最大子数组和
这道题跟上道题,都感觉贪心有点牵强,这道题就是在遍历时候,当和小于0,也就是负数的时候重新计数,因为,一旦和是负数了,则就是拉低整体和的,所以就不能算最大值,因此当和为负数时,更新和为0,也就是变量调整了起始位置。

int result = INT32_MIN;
        int count = 0;
        for (int i = 0; i < nums.size(); i++) {
   
            count += nums[i];
            if (count > result) {
    // 取区间累计的最大值(相当于不断确定最大子序终止位置)
                result = count;
            }
            if (count <= 0) count = 0; // 相当于重置最大子序起始位置,因为遇到负数一定是拉低总和
        }
        return result;

相关推荐

  1. day 31 贪心1

    2023-12-30 13:12:04       63 阅读
  2. day31 算法 贪心算法1

    2023-12-30 13:12:04       37 阅读
  3. day 31贪心

    2023-12-30 13:12:04       65 阅读
  4. Day31 贪心算法

    2023-12-30 13:12:04       43 阅读
  5. 算法训练day31贪心算法part1

    2023-12-30 13:12:04       47 阅读
  6. day32 贪心(2)

    2023-12-30 13:12:04       59 阅读
  7. day32 贪心

    2023-12-30 13:12:04       56 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2023-12-30 13:12:04       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2023-12-30 13:12:04       100 阅读
  3. 在Django里面运行非项目文件

    2023-12-30 13:12:04       82 阅读
  4. Python语言-面向对象

    2023-12-30 13:12:04       91 阅读

热门阅读

  1. Dockerfile文件介绍

    2023-12-30 13:12:04       58 阅读
  2. nginx配置文件

    2023-12-30 13:12:04       60 阅读
  3. MFC:如何将JPEG等图片显示到对话框客户区

    2023-12-30 13:12:04       53 阅读
  4. journalctl命令学习

    2023-12-30 13:12:04       56 阅读
  5. 第一篇 设计模式引论 - 探索软件设计的智慧结晶

    2023-12-30 13:12:04       54 阅读
  6. 二、计算机软件及其使用-电子表格软件Excel 2016

    2023-12-30 13:12:04       60 阅读