花了二十多天,跟着卡尔老师学完了贪心算法章节,总体来说贪心算法简单题可能往往过于简单,让人感觉不到贪心,难题又真的很难。总体来说贪心算法没什么解题套路,不同的题目思路完全不一样,但整体都是通过局部最优推出全局最优,并且找不出反例,即可认为是贪心的题目。
贪心简单题
- 455 分发饼干
- 局部最优,大饼干优先满足大胃口,全局最优,用尽可能多的饼干喂饱小孩,并且举不出反例
- 1005 K次取反后最大化的数组和
- 首先对数组按照绝对值从大到小排序
- 局部最优,优先把负数变为正数,对总累加和贡献尽可能大,全局最优,最终的总累加和最大
- 最后如果变换次数k没用完,则把数组中最小的那个树进行变换k次即可
- 860 柠檬水找零
- 首先明确找零场景,对于5元直接收下;对于10元,只能用5元找零;对于20元,要么找零一个10块,一个5块,要么找零三个5元
- 很明显5元可以满足更多的找零场景(10和20元)
- 局部最优,应该优先把10元的用掉,留下更万能的5元可以满足更多的找零场景,全局最优,保证尽可能多的找零
贪心中等题
- 376 摆动序列
-
首先弄清楚怎么判断是不是单调坡;其次对于两个数字的场景,应该默认第一个数字前面有一个同第一个一样的数字(令result=1);
-
上下坡中有平坡的场景,(preDiff <= 0 && curDiff > 0) || (preDiff >= 0 && curDiff < 0)
-
单调破中有平坡的场景(有摆动变化的时候更新prediff)
-
局部最优:删除单调坡度上的节点(不包括单调坡度两端的节点),那么这个坡度就可以有两个局部峰值。
-
整体最优:整个序列有最多的局部峰值,从而达到最长摆动序列。
-
- 738 单调递增的数字
- 以98为例,一旦出现strNum[i - 1] > strNum[i]的情况(非单调递增),首先想让strNum[i - 1]--,然后strNum[i]给为9,这样这个整数就是89,即小于98的最大的单调递增整数。
- 那么是从前往后遍历还是从后往前遍历呢?
- 如果从前往后便利,以332例,从前往后遍历,变成329,但是2又小于3,真正的结果应该是299。
- 从后往前遍历,就可以重复利用上一次比较的结果了,332-〉329-〉299
贪心解决股票问题
- 122 买卖股票的最佳时机II
- 714 买卖股票的最佳时机含手续费
两个维度权衡的贪心问题
- 135 分发糖果
- 406 根据身高重建队列
整体思路就是求出每一天的利润,注意利润是从第二天开始计算的,然后把所有正利润相加即得到最大的股票收益。局部最优:某天正收益的时候买卖,全局最优,最终收益最大。
贪心难题
贪心解决区间问题
- 55 跳跃游戏
- 45 跳跃游戏II
- 452 用最少数量的箭引爆气球
- 435 无重叠区间
- 763 划分字母区间
- 56 合并区间
贪心算法解决区间问题,一般首先都是对区间按照区间左边或者右边进行排序,然后遍历排序后的序列,当区间有重复时,在原来序列上更新重复边界,然后继续比较更新后的边界与新的边界关系,并累加结果值
其他难题
- 53 最大子序和
- 其实是动态规划的题目,但贪心性能更优
- 134 加油站
- 可能以为是一道模拟题,但就算模拟其实也不简单,需要把while用的很娴熟。但其实是可以使用贪心给时间复杂度降低一个数量级。
- 968 监控二叉树
- 不仅贪心的思路不好想,而且需要对二叉树的操作特别娴熟,这就是典型的交叉类难题了。