代码随想录算法训练营day27

代码随想录算法训练营

---day27

文章目录


前言

今天是算法营的第27天,希望自己能够坚持下来!

今日任务:

● 贪心算法理论基础

● 455.分发饼干

● 376. 摆动序列

● 53. 最大子序和


一、贪心算法理论基础

文章讲解
视频讲解

题目大纲:

贪心的本质是选择每一阶段的局部最优,从而达到全局最优。

贪心没有套路,说白了就是常识性推导加上举反例。贪心的题目要么很简单,要么没做过就想不出来思路。遇到没思路的题目不要想太久,马上看题解积累思路。


二、455.分发饼干

题目链接
文章讲解
视频讲解

思路:

  1. 这里的局部最优是,尽量用大的饼干去满足大的胃口(或者反过来用小的饼干满足小的胃口)
  2. 先对饼干和胃口排序
  3. 从后往前遍历胃口,优先用最大的饼干去匹配大胃口
  4. 如果满足的话则饼干index往前(这里要注意index>=0),累加计数。

代码如下:

cpp 复制代码
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;
    }
};

三、376. 摆动序列

题目链接
文章讲解
视频讲解

局部最优:删除单调坡度上的节点(不包括单调坡度两端的节点),那么这个坡度就可以有两个局部峰值(头和尾)。

整体最优:整个序列有最多的局部峰值,从而达到最长摆动序列。

因为题目要求的是最长摆动子序列的长度,所以只需要统计数组的峰值数量就可以了

思路:

  1. 用当前元素分别和前一元素,后一元素的差的正负来判断是否有摆动;
  2. preDiff = numsi + 1 - numsi,curDiff = numsi - numsi - 1
  3. preDiff和curDiff一正一负时说明出现了摆动。

这是我们思考本题的一个大体思路,但本题要考虑三种情况:

情况一:上下坡中有平坡

平坡有4个2,那么考虑删掉左边3个2的话,遍历到最后一个2时的条件就是prediff = 0 && curdiff < 0,所以判断峰值的条件就应该是:

(preDiff <= 0 && curDiff > 0) || (preDiff >= 0 && curDiff < 0)

情况二:数组首尾两端

题目中说了,如果只有两个不同的元素,那摆动序列也是 2。

那么为了统计到这种情况,默认最右端是一个摆动,result初始化为1,且遍历只遍历到倒数第二个,i < nums.size() - 1;再加上情况一讨论的判断条件 curDiff > 0 && preDiff <= 0,那么result++,就会得到答案2.

情况三:单调坡中有平坡

为了避免nums1和nums2都各自统计了一次摆动,只需要在这个坡度摆动变化的时候,更新 prediff 就行(也就是图上的1),这样 prediff 在 单调区间有平坡的时候 就不会发生变化,造成我们的误判。

cpp 复制代码
class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        if (nums.size() <= 1) return nums.size();

        int preDiff = 0; //nums[i + 1] - nums[i]
        int curDiff = 0; //nums[i] - nums[i - 1]
        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;
    }
};

53. 最大子数组和

题目链接
文章讲解
视频讲解

思路:

  1. 当累加和是负数时,继续往后加都是让后面的数更加小
  2. 所以当累加和为负时,舍弃掉当前的累加,重新从下一个元素开始累加,并且在过程中记录累加的最大值。

代码如下:

cpp 复制代码
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        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;
    }
};

总结

今天第一天的贪心算法,代码其实都不难,难的是思路,需要多积累一些解题思路才行。

明天继续加油!

相关推荐
AI小码10 小时前
如何让AI帮你构建项目?七级方法
人工智能·算法·计算机·ai·程序员·大模型·编程
1000世界小札10 小时前
排序算法全景总结:从 O(n²) 到 O(n log n),再到线性时间(附完整对比与选型指南)
数据结构·算法·排序算法
一直C11 小时前
【Linux应用编程】深入理解Linux多任务机制:进程原理、状态转换与进程控制实战
linux·开发语言·算法·ubuntu·vim·visual studio code
qz5zwangzihan111 小时前
AtCoder高频英文词汇短语
c++·atcoder·高频词
码匠许师傅11 小时前
【C++ 面试真题】聊聊 C++ 的类型特征( type_traits)
java·c++·面试
小小龙学IT11 小时前
C++ 性能优化:CPU 缓存与数据布局优化深度解析
c++·缓存·性能优化
玉树临风ives11 小时前
atcoder ABC 472 题解
数据结构·c++·算法
AI服务老曹11 小时前
抽烟识别算法接入 AI 视频分析平台的流程与误报优化指南
人工智能·算法·音视频
阳明山水11 小时前
销量预测2025—2026:技术演进、实证发现与系统架构的系统性综述
人工智能·深度学习·算法·机器学习·架构
伯远医学11 小时前
RIP-seq 高分文献案例分享
java·前端·javascript·人工智能·算法·eclipse·html