摸不准啥时候用贪心,Carl哥总结的贪心思路:贪心的本质是选择每一阶段的局部最优,从而达到全局最优。如果找到局部最优,然后推出整体最优,那么就是贪心。 所以贪心本质是局部最优推出全局最优。但仔细观察贪心的题貌似dp又都能解决...
122. 买卖股票的最佳时机 II
这里可以选择第一天买入股票,第二天就把股票卖出,假如是正收益,那么我们就获得了一个局部最优值,负收益的话不计入即可。这道题用贪心思想做反而会比用dp简单的多。
class Solution {
public int maxProfit(int[] prices) {
int result = 0;
for(int i = 1; i < prices.length; i ++){
result += Math.max(0, prices[i] - prices[i - 1]);
}
return result;
}
}
55. 跳跃游戏
这题主要并不在于跳跃过程中应该选择跳几步,而是只需要思考所给选择的跳跃步数是否能把整个数组都跳完。也就是说跳跃的覆盖范围是否能比数组长度大,如果可以就能直接返回true了。每次移动取最大跳跃步数(得到最大的覆盖范围),每移动一个单位,就更新最大覆盖范围。贪心算法局部最优解:每次取最大跳跃步数(取最大覆盖范围),整体最优解:最后得到整体最大覆盖范围,看是否能到终点。
class Solution {
public boolean canJump(int[] nums) {
if(nums.length == 1) return true;
int coverLength = 0;
for(int i = 0; i <= coverLength; i ++){
//这里注意用i+num[i]而不是num[i]的原因是,每次可跳跃的范围是在当前我所站在的格子位置+格子所在的数组给我的范围。
coverLength = Math.max(coverLength, i+nums[i]);
if(coverLength >= nums.length - 1){
return true;
}
}
return false;
}
}
45. 跳跃游戏 II
理解本题的关键在于:以最小的步数增加最大的覆盖范围,直到覆盖范围覆盖了终点,这个范围内最小步数一定可以跳到,不用管具体是怎么跳的,不纠结于一步究竟跳一个单位还是两个单位。
class Solution {
public int jump(int[] nums) {
int res = 0;
int temp = 0;
int end = 0;
for(int i = 0; i <= end && end < nums.length - 1; i ++){
temp = Math.max(temp, i + nums[i]);
if(i == end){
end = temp;
res ++;
}
}
return res;
}
}