代码随想录第三十一天 贪心算法:理论基础 、 455.分发饼干 、376. 摆动序列 、53. 最大子序和

这是贪心算法第一天:

首先了解了贪心算法,贪心算法是选择每一部局部最优以达到全局最优解,贪心有四个步骤 1)

 455.分发饼干 

题目链接:. - 力扣(LeetCode)

思路:将两个数组,胃口值 g和尺寸s进行排序,用双指针法,如果胃口值小于且等于尺寸值,则次数+ 1,然后移动两个指针的位置,如果不满足条件,则只移动尺寸值的指针,代码实现如下:

var findContentChildren = function (g, s) {
    g.sort((a, b) => a - b);
    s.sort((a, b) => a - b);
    let left = 0, right = 0;
    let count = 0
    while (left < g.length && right < s.length) {
        if (g[left] <= s[right]) {
            count = count + 1;
            left = left + 1;
            right = right + 1
        } else {
            right = right + 1
        }
    }
    return count
};

卡哥思路是用局部最优去推导出全局最优,这里的局部最优是用最大的尺寸去满足最大的胃口,我感觉和双指针的思路其实类似;

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

376. 摆动序列 

题目链接:. - 力扣(LeetCode)

这道题分析了一下还是比较懵的,既要求差值为摆动序列的,而且这个摆动序列还可以是去掉一些值后形成的子序列的个数;看完卡哥的讲解整理了一下思路:

1) 首先如果要形成摆动序列,那么就会存在峰值的情况也就是存在 preDiff >0 且 curDiff < 0 以及 preDiff < 0 且 curDiff > 0的情况;在做判断之后,去更新 preDiff为 curDiff的情况

2) 但是这样的话,其实是忽略了首尾的情况,那么假设首尾还有一个元素,是和首尾元素相同的元素,那么其实应该是preDiff >=0 且 curDiff < 0 以及 preDiff <= 0 且 curDiff > 0的情况下,去对 result做增加

3)但是这样并没有通过所有测试用例,因为存在中间是平坡,且单调递增的序列,这样的其实如果也用 preDiff <= 0 且 curDiff > 0这个条件去判断的话,是会多增加一条,因为 preDiff是实时更新的,在中间是平坡时,preDiff 又更新为 0,那么又满足了preDiff <= 0 且 curDiff > 0这个条件,所以出现了多加一次的情况;那其实应该在动态变化记录 result的时候,才去更新 preDiff

实现代码:

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

        }
    }
    return result + 1 // 默认序列最后有一个序列
};

贪心算法:通过找到局部峰值来找到这个数组的最大峰值

53. 最大子序和 

题目链接:. - 力扣(LeetCode)

思路:

暴力解法:通过遍历来对比出最大的和;贪心算法没有什么思路,总结了一下卡哥的思路:

这里局部最优解的定义是,如果当前累加和是负数的情况下遇到了正数,那么直接抛弃前面的累加和,从这个正数开始重新累加;那么实际上的实现思路是,通过 count 来累加,然后将 count 的最大值赋给 result,如果遇到 count 为负数的情况,直接将 count 赋值为 0,因为之前的和都为负数,后面为正数的话,还不如直接从正数开始计算,如果后面是负数的话,继续求和也是会将和减少

/**
 * @param {number[]} nums
 * @return {number}
 */
var maxSubArray = function (nums) {
    let result = Number.MIN_VALUE, count = 0;
    for (let i = 0; i < nums.length; i = i + 1) {
        count = count + nums[i]
        result = Math.max(result, count) // 如果全是负数,这里已经求出来结果了
        if(count < 0) {
            count = 0
        }
    }
    return result
};

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值