代码随想录算法训练营第23天|455.分发饼干、376. 摆动序列、53. 最大子数组和

LeetCode455

2025-02-23 22:15:20 星期日

题目描述:力扣455
文档讲解:代码随想录(programmercarl)455.分发饼干
视频讲解:《代码随想录》算法视频公开课:贪心算法,你想先喂哪个小孩?| LeetCode:455.分发饼干

代码随想录视频内容简记

贪心算法就是通过求得局部最优,来推得一个全局最优

梳理

  1. 首先对g胃口进行排序,s饼干值进行排序

  2. 要做的就是让饼干逐个匹配孩子的胃口值,这是局部最优。之后尽量满足每一个孩子的胃口来求得全局最优

大致代码内容

  1. 对胃口值进行遍历for (int i = g.size() - 1; i >= 0; i--)

  2. 之后对饼干值进行遍历,if (index >= 0 && s[index] >= s[i]) index--; result++;

  3. 这里有一个小细节,那么for循环内就一定是g胃口值,能不能是s饼干值呢?答案是可以的,这是在k哥视频中讲到的从小的饼干开始喂和从大的饼干开始喂联想了一下。

    1. 首先,如果for循环中是g胃口值,那么就只能从大饼干开始喂。

      g[7,8,9,10],s[5,6,7,8]如果从大饼干开始喂,那么就是从后向前遍历,8<10, 8<9,8等于8,这时result+1,7==7,result再+1,能喂两个孩子,没有问题。

      但是从小饼干开始喂,也就是从前向后遍历,5<7,5<8,5<9,5<10,那么result就等于0

    2. 如果for循环中是s饼干值,那么就只能从小饼干开始喂。

      这个也是同理的

    这个的关键就是if条件如果一直得不到满足,那么index的索引就不会发生变化。

LeetCode测试

总结一下,也就是只能是大胃口先得到大饼干,或者小饼干先喂饱小胃口

for中是g胃口值,从大饼干开始喂

点击查看代码
class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        sort(g.begin(), g.end());
        sort(s.begin(), s.end());
        int index = s.size() - 1;
        int result = 0;
        for (int i = g.size() - 1; i >= 0; i--) {
            if (index >= 0 && s[index] >= g[i]) {
                index--;
                result++;
            }
        }
        return result;
    }
};

for中是s饼干值,从小饼干开始喂

点击查看代码
class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        sort(g.begin(), g.end());
        sort(s.begin(), s.end());
        int index = 0;
        int result = 0;
        for (int i = 0; i < s.size(); i++) {
            if (index < g.size() && s[i] >= g[index]) {
                result++;
                index++;
            }
        }
        return result;
    }
};

LeetCode376

题目描述:力扣376
文档讲解:代码随想录(programmercarl)376. 摆动序列
视频讲解:《代码随想录》算法视频公开课:贪心算法,寻找摆动有细节!| LeetCode:376.摆动序列

代码随想录视频内容简记

这个题很难想,需要考虑的情况很多。这个题的局部最优是消除每个顶峰中间的元素,全局最优就是找到一个最长的摆动子序列

梳理

  1. 上下坡有平坡

这种就是需要定义一个prediff和一个curdiff来,如果prediff >= 0 && curdiff < 0或者prediff <= 0 && curdiff > 0,那么就对结果 + 1

  1. 首尾元素

这种就是如果只有两个元素,[2, 5],他的摆动序列就只是2, 但是按照prediff和curdiff最少需要3个元素,那么我们就只能"虚拟"一个头部元素,假设他的prediff=0就不会影响了。

  1. 单调有平坡

这种情况k哥是在最后讲的,这里需要额外注意一个prediff的更新时间

prediff只有在每次发生波动的情况下才会更新,如果他一直是一个单调的坡,那么就不会更新,所以这个prediff = curdiff一定要写在if的条件判断里面

if (prediff >= 0 && curdiff < 0 || prediff <= 0 && curdiff > 0) {
		result++;
		prediff = curdiff;
	}

LeetCode测试

点击查看代码
class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        if (nums.size() == 1) return 1;
        int prediff = 0;
        int curdiff;
        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;
            }
        }
        return result;
    }
};

LeetCode53

题目描述:力扣53
文档讲解:代码随想录(programmercarl)53. 最大子数组和
视频讲解:《代码随想录》算法视频公开课:贪心算法的巧妙需要慢慢体会!LeetCode:53. 最大子序和

代码随想录视频内容简记

这道题的贪心策略就是如果一个数让当前的连续子序和变成了负数,那么他就只会让后面的子序列就立马抛弃这个数,从下一个数开始重新计数。这里的实现就是给count重新赋值为0,那么相当于跳过这个元素从后面的元素重新开始记和。

举个例子

但是如果加一个数,让当前变成正数,他就一定是最大子序列的开始位置吗?这也不一定,如果涉及到了子序列的开始位置和终止位置,情况又会复杂不少。

卡哥视频里记录的这个序列,[4,3,5,6]是最大子序列,如果要是记录他的起始和终止,可能得用双指针来解

LeetCode测试

点击查看代码
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        if (nums.size() == 1) return nums[0];
        int result = INT_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;

    }
};
posted on   bnbncch  阅读(830)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示