【Leetcode每日一刷】贪心算法01:455.分发饼干、376. 摆动序列、53. 最大子序和

  • 博主简介:努力学习和进步中的的22级计科生
  • 博主主页: @Yaoyao2024
  • 每日一句: " 路虽远,行则将至。事虽难,做则可成。"

文章目录

前言:贪心算法

参考和学习:代码随想录

贪心算法并没有任何套路,它的本质是寻找局部最优解

严格的数学证明为以下两者

  • 数学归纳
  • 反证

前者基本上是劝退了,反证就是看能不能对你想出的这种算法or模拟举出反例。与其叫贪心,我个人现在更愿意将其理解为模拟,偏常识形式的,没有一个统一的套路。可以从下面的题目中看出。

一、455.分发饼干

🌷思路:

这题比较简单,当然是先用小的去喂饱小的,依次把饼干由小到大喂完,喂的孩子最多。反例举不出来这种方法不行。

硬要解释的话,可以把**"先用小的去喂饱小的"** 理解为局部最优解:给每个孩子满足胃口且尺寸最小的饼干 。然后顺序进行便得到了全局最优解

🌻步骤

  • 首先对gs数组进行排序

  • 外层循环遍历s,表示对每个饼干进行分发。

  • 用坐标ig表示遍历到了哪个孩子

    • 如果此时s[i]>g[ig],ig++
    • 否则ig不变,i++,看看还有没有更大的饼干能满足当前孩子的胃口
  • 最后返回ig,表示当前喂了多少个孩子

🏄🏻‍♀️完整代码

cpp 复制代码
class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        sort(g.begin(),g.end());
        sort(s.begin(),s.end());
        int ig = 0;
        for(int i = 0; i < s.size(); i++){
            if(ig< g.size()&&s[i]>= g[ig]){
                ig++;
            }else{
                continue;
            }
        }
       return ig;
    }
};

二、376. 摆动序列

力扣题目链接

🌷思路:

这题的话,用贪心做复杂了。其实弄清楚这个题的本质:数一数:上坡+下坡,加起来即可。这里用图来表示:

🏄🏻‍♀️完整代码

cpp 复制代码
class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
    int flag = -1;//0表示下坡,1表示上坡
    //if (nums.size() == 0) return 1;
    int ans = 0;
    for(int i = 1; i < nums.size(); i++){
        bool down = (nums[i] - nums[i-1] < 0) && (flag != 0);
        bool up = (nums[i] - nums[i-1] > 0) && (flag != 1);
        if(down){
            flag = 0;
            ans++;
        }else if (up){
            flag = 1;
            ans++;
        }
    }
    return ans+1;//res是两两比较得来的值,差一个边界值要+1!

    }
};

三、53. 最大子序和

题目链接

🌷思路:

这题的暴力解法就是两层for循环,不在这里赘述。

这题我没想出来的核心是:我没想到最终答案由"擂台法"得来。当前的连续子序列的和不一定是答案,它只是当前的计算,它和已经记录下来的当前的最大连续和进行相比,如果小于它,则不更新答案。

那再说回这道题的思路:

cpp 复制代码
  • 局部贪心-12,当然不要-1,因为前面是负数总会拖累后面的。于是放弃前面的负数,用后面的2重新当作子序列的开头。
  • 全局最优:一旦当前子序列的和为负数,立马放弃当前子序列,从下一个元素开头,重新计算子序列的和。

用代码来说就是,设计一个res= INT32_MIN用来存储最终结果,count=0实时记录当前连续字串的和。若加上nums[i]count<0,那么放弃当前字串,令count = 0,以nums[i+1]开始重新计算连续字串长度。

这样严谨吗?没有数学证明确实不好说,但是你完全找不到反例,因此这个算法就是OK的。贪心就是比较魔幻。我一开始对这个代码思路提出下面的反例:加上-3后,前面为负,从5元素开始计算,结果肯定是5;但是明显结果是[4,-3,5,-1,1]更大;我忽略了一点是,-2在最开始就不可能做连续字串的开头!

❌错误代码:

cpp 复制代码
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int result = INT32_MIN;
        int count = 0;
        for (int i = 0; i < nums.size(); i++){
            count += nums[i];
            if(count < 0){
                count = 0;
            }else{
                result = max(result, count);
            }
        }
        return result;
    }
};

错误原因:忽略了以下情况。也就是说,result = max(result, count);必须在count += nums[i];立马进行比较进行,它是不存在有调节的!!

✅正确代码:

cpp 复制代码
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int result = INT32_MIN;
        int count = 0;
        for (int i = 0; i < nums.size(); i++){
            count += nums[i];
            result = max(result, count);
            if(count < 0){
                count = 0;
            }
        }
        return result;
    }
};
相关推荐
南东山人4 小时前
一文说清:C和C++混合编程
c语言·c++
LNTON羚通5 小时前
摄像机视频分析软件下载LiteAIServer视频智能分析平台玩手机打电话检测算法技术的实现
算法·目标检测·音视频·监控·视频监控
哭泣的眼泪4086 小时前
解析粗糙度仪在工业制造及材料科学和建筑工程领域的重要性
python·算法·django·virtualenv·pygame
Ysjt | 深6 小时前
C++多线程编程入门教程(优质版)
java·开发语言·jvm·c++
ephemerals__6 小时前
【c++丨STL】list模拟实现(附源码)
开发语言·c++·list
Microsoft Word7 小时前
c++基础语法
开发语言·c++·算法
天才在此7 小时前
汽车加油行驶问题-动态规划算法(已在洛谷AC)
算法·动态规划
一只小小汤圆7 小时前
opencascade源码学习之BRepOffsetAPI包 -BRepOffsetAPI_DraftAngle
c++·学习·opencascade
legend_jz7 小时前
【Linux】线程控制
linux·服务器·开发语言·c++·笔记·学习·学习方法