贪心算法part01
贪心算法
贪心的本质是选择每一阶段的局部最优,从而达到全局最优。
LC445分发饼干
- 局部最优就是充分利用饼干尺寸喂饱一个,全局最优就是喂饱尽可能多的小孩。
- 代码
LC376摆动序列(未掌握)
- 贪心思想:
- 局部最优:删除单调坡度上的节点(不包括单调坡度两端的节点),那么这个坡度就可以有两个局部峰值。
- 整体最优:整个序列有最多的局部峰值,从而达到最长摆动序列
- 对于下标i,和prediff=nums[i] - nums[i-1] 、curdiff=nums[i+1] - nums[i],有四种情况需要考虑
-
普通情况:如果prediff < 0 && curdiff > 0 或者 prediff > 0 && curdiff < 0 此时就有波动就需要统计。
-
上下坡中有平坡:如[1,2,2,2,1]:这种情况要不选择最左边的计数要不选择最右边的计数,统一选择最右边进行计数。条件为(preDiff <= 0 && curDiff > 0) || (preDiff >= 0 && curDiff < 0)
- 如果选择的是最左边进行计数,条件为(preDiff < 0 && curDiff >= 0) || (preDiff > 0 && curDiff =< 0)
-
上诉情况适合i左右均存在数值的情况,如果数组只有两个元素或者i来到了nums[0]和nums[nums.length()-1]位置将不在受用
- 方法一:写死其余的情况,然后i从1开始遍历到nums.length()-2。就是如果只有两个元素,且元素不同,那么结果为 2。如果只有一个元素结果为1
- 方法二:不写死与上诉规则合并,将result和preDiff的初始值定义为1和0,i从0开始遍历到nums.length()-1。如序列[2,5],假设序列为[2,2,5],这样对于原本位置0上的元素2就有了preDiff=0,最后一个元素不遍历是因为最后一个元素必定摆动序列的一员,我们通过初始化result=1来定义。
-
单调坡度有平坡:如[1,2,2,2,3,4],在1和最右边的2分别记录了值,result=3,但是result的值实际应该是2。错误原因在于上诉代码是否达到峰值i都会更新preDiff,但是其实preDiff的值是没有意义的,正负才是有意义的,因此只有变换坡度的时候才更新preDiff,这样就不会再单调有平坡的案例中出错
-
- 代码
LC53最大子数组和
- 动态规划的思想:dp[i]表示以nums[i]为结尾的连续子数组中序列和最大是dp[i]
- 代码
- 贪心:
- 局部最优:当前“连续和”为负数的时候立刻放弃,从下一个元素重新计算“连续和”,因为和已经为负数了,如果下一个数仍然是负,两者相加只会更小,如果是正数,那直接用该正数替代连续和即可
- 局部最优:当前“连续和”为负数的时候立刻放弃,从下一个元素重新计算“连续和”,因为和已经为负数了,如果下一个数仍然是负,两者相加只会更小,如果是正数,那直接用该正数替代连续和即可