代码随想录算法训练营第二十七天| 贪心算法理论基础 455.分发饼干 376. 摆动序列 53. 最大子序和


一、贪心算法理论基础

贪心算法:对于一个问题,通过做出若干次决策来解决,在其中的每一步决策中只选取当前情况下的局部最优解,这样每一步的局部最优解可以组合成为原问题的整体最优解,这样的算法称为贪心算法。

使用贪心算法需要满足最优子结构性质和贪心选择性质。

 对于贪心算法的使用比贪心算法的构建要容易一些,需要先判断该问题能否满足贪心选择性质(数学归纳法,反证法)。贪心算法的构建根据每一步的最优,直觉地选择答案即可编写出贪心算法。

 对于具体的使用情形,仍然需要一定的经验和对问题的敏感度(即,刷题)来评判。那么开始刷题吧。

二、LeetCode 455.分发饼干

题目链接:LeetCode 455.分发饼干

文章讲解:代码随想录
视频讲解:贪心算法,你想先喂哪个小孩?| LeetCode:455.分发饼干

思路

 本题的贪心选择策略较为显而易见,我们需要让满足的孩子数量尽可能的多,那么我们可以优先用小饼干去满足胃口最小的孩子,将较大的饼干留给胃口大的孩子。即从小到大遍历饼干,直到饼干可以满足当前没有吃到饼干的最小胃口的孩子为止。

C++代码

class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        sort(g.begin(), g.end());//饼干和孩子胃口进行排序
        sort(s.begin(), s.end());
        int kid = 0, cookie = 0;
        while(kid < g.size() && cookie < s.size()){ 
        //从小到大遍历饼干和孩子胃口
            if(s[cookie] >= g[kid]){
                kid++;
                cookie++;
            }
            else cookie++;
        }
        return kid;
    }
};

三、LeetCode 376. 摆动序列

题目链接:LeetCode 376. 摆动序列

文章讲解:代码随想录
视频讲解:贪心算法,寻找摆动有细节!| LeetCode:376.摆动序列

思路

 要求返回可以被构造出的最长的摆动序列长度,笔者初刷的思路为:设置len记录当前摆动序列长度;b为序列指针,指示当前判定的数字;设置布尔值diff来判断下一个数应该是正数还是负数。diff的初始值取决于序列第一个数,算法进行时仅需要每次取出b位置的数字,对照diff指示的正负进行比对即可,若符合,则len++,否则不变,最后返回len作为摆动序列的长度。

C++代码

一刷代码

class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        if(nums.size() == 1) return 1;
        int len = 2, b = 1;
        bool diff;
        while(b < nums.size() && nums[b] == nums[b-1]){
            b++;
        }
        if(b == nums.size()) return 1;

        if(nums[b] > nums[b-1]) diff = false;
        else diff = true;

        for(int i = b+1; i < nums.size(); i++){
            if(diff && nums[i] > nums[i-1] || !diff && nums[i] < nums[i-1]){
                len++;
                diff = !diff;
            }
        }
        return len;
    }
};

四、LeetCode 53. 最大子序和

题目链接:LeetCode 53. 最大子序和

文章讲解:代码随想录
视频讲解:贪心算法的巧妙需要慢慢体会!LeetCode:53. 最大子序和

思路

 本题的贪心思路主要在两个方面:

  1. 在数组中,只选择正数作为子数组开始位置;
  2. 每当当前的数组总和小于 0 0 0 时,将sum 0 0 0 ,并重新选取子数组的开头.

 两个贪心选择规则都能保证选取到最优的子数组总和,并且每当出现更大的sum时,将更优值记录在max中,最终输出max即可。

C++代码

class Solution {
private:
    int sum;
    int max = INT_MIN;
public:
    int maxSubArray(vector<int>& nums) {
        sum = nums[0];
        max = nums[0];
        for(int i = 1; i < nums.size(); i++){
            if(sum < 0){
                sum = 0;
            }
            sum += nums[i];
            if(sum > max) max = sum;
        }
        return max;
    }
};


总结

 贪心算法的设计思路有待琢磨


文章图片来源:代码随想录 (https://programmercarl.com/)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值