贪心算法part1 | ● 455.分发饼干 ● 376. 摆动序列 ● 53. 最大子序和

文章目录

  • 455.分发饼干
    • 思路
    • 思路代码
    • 困难
  • 376. 摆动序列
    • 思路
    • 思路代码
    • 困难
  • 53.最大子序和
    • 思路
    • 思路代码
    • 困难
  • 今日收获


455.分发饼干

455.分发饼干

思路

贪心思想
先将小孩和饼干排序
局部最优将最大的饼干分给胃口最大的小孩
循环逻辑,外层循环控制小孩,内层移动饼干

思路代码

func findContentChildren(g []int, s []int) int {
    sort.Ints(g)
    sort.Ints(s)
    index,res:=len(s)-1,0
    for i:=len(g)-1;i>=0;i--{
        if index>=0&&s[index]>=g[i]{
            res++
            index--
        }
    }
    return res
}

困难

外层循环选择小孩


376. 摆动序列

376.摆动序列

思路

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

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

局部最优推出全局最优,并举不出反例,那么试试贪心!

(为方便表述,以下说的峰值都是指局部峰值)

实际操作上,其实连删除的操作都不用做,因为题目要求的是最长摆动子序列的长度,所以只需要统计数组的峰值数量就可以了(相当于是删除单一坡度上的节点,然后统计长度)

这就是贪心所贪的地方,让峰值尽可能的保持峰值,然后删除单一坡度上的节点

在计算是否有峰值的时候,大家知道遍历的下标 i ,计算 prediff(nums[i] - nums[i-1]) 和 curdiff(nums[i+1] - nums[i]),如果prediff < 0 && curdiff > 0 或者 prediff > 0 && curdiff < 0 此时就有波动就需要统计。

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

情况一:上下坡中有平坡
情况二:数组首尾两端
情况三:单调坡中有平坡

思路代码

func wiggleMaxLength(nums []int) int {
    res:=1
    pre:=0
    for i:=0;i<len(nums)-1;i++{
        cur:=nums[i+1]-nums[i]
        if (pre<=0&&cur>0)||(pre>=0&&cur<0){
            res++
            pre=cur
        }
    }
    return res
}

困难

峰值统计三种情况


53.最大子序和

53.最大子序和

思路

贪心贪的是哪里呢?

如果 -2 1 在一起,计算起点的时候,一定是从 1 开始计算,因为负数只会拉低总和,这就是贪心贪的地方!

局部最优:当前“连续和”为负数的时候立刻放弃,从下一个元素重新计算“连续和”,因为负数加上下一个元素 “连续和”只会越来越小。

全局最优:选取最大“连续和”

局部最优的情况下,并记录最大的“连续和”,可以推出全局最优。

从代码角度上来讲:遍历 nums,从头开始用 count 累积,如果 count 一旦加上 nums[i]变为负数,那么就应该从 nums[i+1]开始从 0 累积 count 了,因为已经变为负数的 count,只会拖累总和。

这相当于是暴力解法中的不断调整最大子序和区间的起始位置。

那有同学问了,区间终止位置不用调整么? 如何才能得到最大“连续和”呢?

区间的终止位置,其实就是如果 count 取到最大值了,及时记录下来了。例如如下代码:

if (count > result) result = count;
这样相当于是用 result 记录最大子序和区间和(变相的算是调整了终止位置)。

思路代码

func maxSubArray(nums []int) int {
    res,count:=nums[0],0
    for i:=0;i<len(nums);i++{
        if count+nums[i]<0{
            if res<nums[i]{
                res=nums[i]
            }
            count=0
        }else{
            count+=nums[i]
            if res<count{
                res=count
            }
        }
    }
    return res
}

困难

判断负数,如果数组全是负数?


今日收获

贪心算法,确定局部最优解,结合叠加得到全局最优解。
贪心策略的选取尤为重要,要明白贪心贪的是哪里。

你可能感兴趣的:(算法题,贪心算法,算法,数据结构)