LeetCode刷题------贪心算法

什么是贪心

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

贪心一般解题步骤

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

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

这个四步其实过于理论化了,我们平时在做贪心类的题目 很难去按照这四步去思考,真是有点“鸡肋”。做题的时候,只要想清楚 局部最优 是什么,如果推导出全局最优,其实就够了。

LeetCode刷题

LeetCode455:分发饼干

思路:为了满足更多的小孩,就不要造成饼干尺寸的浪费。大尺寸的饼干既可以满足胃口大的孩子也可以满足胃口小的孩子,那么就应该优先满足胃口大的。这里的局部最优就是大饼干喂给胃口大的,充分利用饼干尺寸喂饱一个,全局最优就是喂饱尽可能多的小孩。可以尝试使用贪心策略,先将饼干数组和小孩数组排序。然后从后向前遍历小孩数组,用大饼干优先满足胃口大的,并统计满足小孩数量。

455.分发饼干

想清楚局部最优,想清楚全局最优,感觉局部最优是可以推出全局最优,并想不出反例,那么就试一试贪心

var findContentChildren = function(g, s) {
    g = g.sort((a, b) => a - b);
    s = s.sort((a, b) => a - b);
    let res = 0;
    let index = s.length - 1;
    for (let i = g.length - 1; i>= 0; i--) {
        if (index >= 0 && s[index] >= g[i]) {
            res ++;
            index --;
        }
    }
    return res;
};

LeetCode376:摆动序列

本题要求通过从原始序列中删除一些(也可以不删除)元素来获得子序列,剩下的元素保持其原始顺序。举例说明:376.摆动序列

 

局部最优:删除单调坡度上的节点(不包括单调坡度两端的节点),那么这个坡度就可以有两个局部峰值整体最优:整个序列有最多的局部峰值,从而达到最长摆动序列。局部最优推出全局最优,并举不出反例,那么试试贪心!实际操作上,其实连删除的操作都不用做,因为题目要求的是最长摆动子序列的长度,所以只需要统计数组的峰值数量就可以了(相当于是删除单一坡度上的节点,然后统计长度)。这就是贪心所贪的地方,让峰值尽可能的保持峰值,然后删除单一坡度上的节点。

var wiggleMaxLength = function(nums) {
    if (nums.length <= 1) {
        return nums.length;
    }
    let result = 1;
    let preDiff = 0;
    let curDiff = 0;
    for (let i = 0; i < nums.length - 1; i++) {
        curDiff = nums[i + 1] - nums[i];
        if ((curDiff > 0 && preDiff <= 0) || (curDiff < 0 && preDiff >= 0)) {
            result ++;
            preDiff = curDiff;
        }
    }
    return result;
};

<扩展>动态规划

var wiggleMaxLength = function(nums) {
    if (nums.length === 1) return 1; 
    // 考虑前i个数,当第i个值作为峰谷时的情况(则第i-1是峰顶)
    let down = 1;
    // 考虑前i个数,当第i个值作为峰顶时的情况(则第i-1是峰谷)
    let up = 1;
    for (let i = 1; i < nums.length; i++) {
        if (nums[i] < nums[i - 1]) {
            down = Math.max(up + 1, down);
        }
        if (nums[i] > nums[i - 1]) {
            up = Math.max(down + 1, up)
        }
    }
    return Math.max(down, up);
};

LeetCode53:最大子序和

局部最优:当前“连续和”为负数的时候立刻放弃,从下一个元素重新计算“连续和”,因为负数加上下一个元素 “连续和”只会越来越小。全局最优:选取最大“连续和”。局部最优的情况下,并记录最大的“连续和”,可以推出全局最优

var maxSubArray = function(nums) {
    let result = -Infinity
    let count = 0
    for(let i = 0; i < nums.length; i++) {
        count += nums[i]
        if(count > result) {
            result = count
        }
        if(count < 0) {
            count = 0
        }
    }
    return result
};

<扩展>动态规划    代补上

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值