Day 31
376. 摆动序列
局部最优:删除单调坡度上的节点(不包括单调坡度两端的节点),那么这个坡度就可以有两个局部峰值。
整体最优:整个序列有最多的局部峰值,从而达到最长摆动序列。
class Solution {
public int wiggleMaxLength(int[] nums) {
if (nums.length <= 1) return nums.length;
int curDiff = 0;
int preDiff = 0;
int res = 1; // 默认序列最右边有一个峰值
for (int i = 0; i < nums.length - 1; i++) {
curDiff = nums[i + 1] - nums[i];
if ((preDiff <= 0 && curDiff > 0) || (preDiff >= 0 && curDiff < 0)) {
res++;
preDiff = curDiff; // 只在摆动变化时,更新prediff
}
}
return res;
}
}
53. 最大子数组和
贪心思路:最大连续子数组和不以负数开头
Day 32
45. 跳跃游戏Ⅱ
思路:
返回到达数组最后一个元素的最小跳跃次数。
贪心的思路,局部最优:当前可移动距离尽可能多走,如果还没到终点,步数再加一。整体最优:一步尽可能多走,从而达到最少步数。
使用curRange 和 nextRange 表示当前跳跃覆盖的范围以及下一步覆盖的范围。
遍历时,当 遍历位置 i == curRange 时在 跳跃数再加一,同时更新curRange = nextRange
nextRange = Math.max(nextRange, i + num[i])
Day 33
134. 加油站
思路:
首先如果总油量减去总消耗大于等于零那么一定可以跑完一圈,说明 各个站点的加油站 剩油量rest[i]相加一定是大于等于零的。
rest[i] 数组表示每个城市需要消耗的汽油的剩余值 gas[i] - cost[i]
totalSum 为整个 rest 数组之和。
贪心思路:i从0开始累加rest[i],和记为curSum,一旦curSum小于零,说明[0, i]区间都不能作为起始位置,因为这个区间选择任何一个位置作为起点,到i这里都会断油,那么起始位置从i+1算起,再从0计算curSum。
那么局部最优:当前累加rest[i]的和curSum一旦小于0,起始位置至少要是i+1,因为从i之前开始一定不行。全局最优:找到可以跑一圈的起始位置。
135. 分发糖果
思路:
这道题目一定是要确定一边之后,再确定另一边,例如比较每一个孩子的左边,然后再比较右边,如果两边一起考虑一定会顾此失彼。
先确定右边评分大于左边的情况(也就是从前向后遍历)
此时局部最优:只要右边评分比左边大,右边的孩子就多一个糖果,全局最优:相邻的孩子中,评分高的右孩子获得比左边孩子更多的糖果
局部最优可以推出全局最优。
Day 34
406.根据身高重建队列
思路:
跟之前分发糖果类似
存在两个维度,所以先确定一个维度,再根据另外一个维度调整数组。
其技巧都是确定一边然后贪心另一边,两边一起考虑,就会顾此失彼。
452. 用最少数量的箭引爆气球
思路:
同样先安其中一个维度排序
如按第一个维度排序,从前向后遍历
重叠的气球,要看最小的右边界,
如果下一个气球的左边界 > 上一个气球的最小右边界,则需要一支箭。
难点在于 思路想好了,如果模拟气球被箭射爆的过程。