贪心算法总结
本总结参考:代码随想录 - 贪心算法总结篇
个人心得
问题本质
贪心算法没有固定套路、模板,需要具体题目具体分析,如果发现可以通过局部最优推导出全局最优,且没有反例,便可以尝试利用贪心算法解题。
解题步骤
- 将问题分解为若干个子问题
- 找出适合的贪心策略
- 求解每一个子问题的最优解
- 将局部最优解堆叠成全局最优解
其实这个分的有点细了,真正做题的时候很难分出这么详细的解题步骤,可能就是因为贪心的题目往往还和其他方面的知识混在一起。
题目集合
叙述几个思路巧妙,令人眼前一亮,自己第一遍做一定想不出来的题。
简单题目
860. 柠檬水找零 - 力扣(LeetCode),蛮有意思,只用记录5、10元的个数,若是碰到20,优先用10元+5元找零而不是3个五元
序列问题
376. 摆动序列 - 力扣(LeetCode),直呼nb,最左右两边的峰值不好记录,维护curdiff和prediff,prediff 一定要包含和0的比较,因为我们假设了在nums[0]的左边还有一个一样高的山峰,result初始为1(默认最右面有一个峰值),这题思路还是要好好理一理
738. 单调递增的数字 - 力扣(LeetCode),注意 to_string() 和 stoi() 的用法,从后往前遍历,flag记录9的初始赋值位置
股票问题
122. 买卖股票的最佳时机 II - 力扣(LeetCode),利润拆分,只收集每日正利润
714. 买卖股票的最佳时机含手续费 - 力扣(LeetCode),三种情况,比较难理解
两个维度权衡问题
体会到了算法的奥秘,体会到了仔细分析问题、然后高效解决问题的快感。
135. 分发糖果 - 力扣(LeetCode),先从前到后处理左<右,然后从后向前处理左>右
406. 根据身高重建队列 - 力扣(LeetCode),先按身高降序排序,然后按人数插入
本题需要频繁插入操作,因此选用底层是链表实现的list,插入效率比vector高的多,最后转换为二维vector输出。不然O(n)的算法复杂度会以O(n^2)复杂度实现。
区间问题
452. 用最少数量的箭引爆气球 - 力扣(LeetCode),理解好这道题,其他区间不成问题
55. 跳跃游戏 - 力扣(LeetCode),判断能否跳到,理解覆盖范围而不是看每步如何跳
45. 跳跃游戏 II - 力扣(LeetCode),保证最小跳跃次数跳到,记录当前、下一步最远覆盖范围和步数
其他问题
134. 加油站 - 力扣(LeetCode),首先如果总油量减去总消耗大于等于零那么一定可以跑完一圈,说明 各个站点的加油站 剩油量rest[i]相加一定是大于等于零的,每个加油站的剩余量rest[i]为gas[i] - cost[i]。i从0开始累加rest[i],和记为curSum,一旦curSum小于零,说明[0, i]区间都不能作为起始位置,起始位置从i+1算起,再从0计算curSum。那么局部最优:当前累加rest[j]的和curSum一旦小于0,起始位置至少要是j+1,因为从j开始一定不行。全局最优:找到可以跑一圈的起始位置
加rest[j]的和curSum一旦小于0,起始位置至少要是j+1,因为从j开始一定不行。全局最优:找到可以跑一圈的起始位置
968. 监控二叉树 - 力扣(LeetCode),每个节点三种状态+后序遍历