代码随想录第三十一天 | 贪心理论基础&&分发饼干&&摆动序列&&*最大子序和
贪心算法理论基础
1. 贪心算法理论基础
什么是贪心
贪心的本质是选择每一阶段的局部最优解,从而达到全局最优。
贪心的套路(什么时候用贪心)
说实话贪心算法并没有固定的套路。
所以唯一的难点就是如何通过局部最优,推出整体最优。
那么如何能看出局部最优是否能推出整体最优呢?有没有什么固定策略或者套路呢?
不好意思,也没有! 靠自己手动模拟,如果模拟可行,就可以试一试贪心策略,如果不可行,可能需要动态规划。
有同学问了如何验证可不可以用贪心算法呢?
最好用的策略就是举反例,如果想不到反例,那么就试一试贪心吧。
贪心一般解题步骤
贪心算法一般分四步:
- 将问题分解为若干个子问题
- 找出适合的贪心策略
- 求解每一个子问题的最优解
- 将局部最优解叠成全局最优解
455.分发饼干
文章:2. 分发饼干
题目:455. 分发饼干
【思路】
- Java实现
1 | class Solution { |
- Go实现
1 | func findContentChildren(g []int, s []int) int { |
376.摆动序列
文章:3. 摆动序列
题目:376. 摆动序列
【思路】
局部最优:删除单调坡度上的节点(不包括单调坡度两端的节点),那么这个坡度就可以有两个局部峰值。
整体最优:整个序列有最多的局部峰值,从而达到最长摆动序列。
实际上,我们不用进行删除的操作,只需要统计数组的峰值数量就可以了(相当于是删除单一坡度上的节点,然后统计长度)
也就是prediff > 0 && curdiff <0
和prediff >0 && curdiff <0
两种情况
但我们需要考虑三种情况:
1.上下坡中有平坡(考虑:prediff = 0 &&( curdiff<0 || curdiff >0))
2.数组首尾两端(如果数组只有两个数字,我们可以写死,如果只有两个元素,且元素不同,那么结果为2;如果不写死的话,就假设数组最前面还有一个数字,结合情况一,当相同数字连续的时候,preDiff = 0 && curdiff <0或>0 都记为波谷,那么如果数组只有两个值,就可以将{2,5}假设为{2,2,5},即prediff = 0,curdiff<0)
那么我们现在的条件限制就是:prediff >=0 && curdiff <0 || prediff <=0 && curdiff >0
3.单调坡中有平坡!!
单调中的平坡不能算峰值(摆动)
这是因为我们实时更新了prediff导致出现平坡的时候也记录了其为峰值。
因此我们应该在只有这个坡度摆动变化的时候更新prediff就好了,这样prediff在单调区间有平坡的时候就不会发送变化造成误判。
本题异常情况的本质,就是要考虑平坡, 平坡分两种,一个是 上下中间有平坡,一个是单调有平坡。
- Java实现
1 | class Solution { |
- Go实现
1 | func wiggleMaxLength(nums []int) int { |
53.最大子序和
文章:
题目:
【思路】
- Java实现
1 |
- Go实现
1 |
【算法总结】
- 分发饼干:使用贪心,将胃口和饼干数都进行排序,然后从后往前遍历胃口,判断饼干的饱腹值是否符合小孩胃口,符合就饼干的索引–
- 摆动序列:使用贪心,需要分析两种特殊情况:第一种是平坡(上下平坡,单调值平坡(在出现坡度变化的时候才修改prediff值)),第二种是数组只有两个值(默认左右边有1个峰值)的情况