难度中等2162
给定一个非负整数数组 nums
,你最初位于数组的 第一个下标 。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个下标。
示例 1:
输入:nums = [2,3,1,1,4] 输出:true 解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。
示例 2:
输入:nums = [3,2,1,0,4] 输出:false 解释:无论怎样,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 , 所以永远不可能到达最后一个下标。
提示:
1 <= nums.length <= 3 * 104
0 <= nums[i] <= 105
用贪心做的题会发现代码都非常简单,但是特别难想,非常巧妙吧,虽然大部分都是常识,但是初学大部分都是想不出来,只能多见题型多总结了.
思路
本题题意就是数组中的每一个元素就是你能跳跃的最大长度,问能不能到达终点.
这道题你不用管到底跳几步,怎么跳到终点,你就看能不能到达终点就可以.
问题就可以转化为,你能跳跃的最大范围有没有超过终点下标.
每次跳跃的时候,你只能在你所能跳到的最大范围内进行移动,然后看你跳的最大范围有没有覆盖到终点下标就完事了
- 如何计算当前位置所能跳到的最大范围呢 ?
根据题意数组中的每个元素代表你在该位置可以跳跃的最大长度,而当前位置又是作为起跳点.所以对于一个位置所能跳跃的最大范围就是 i+nums[i](i为起跳点,nums[i]为跳跃的最大长度),并且每一个位置所覆盖的最大跳跃范围不一样,所以要不断地更新最大
所以总结出如下思路 :
- 使用cover来记录最大跳跃范围,并且只能在cover范围内进行移动,每次要对cover更新取最大
- 如果发现cover最大跳跃范围超过了终点下标,那证明可以到达终点返回true,否则的话没有超过终点,返回false
那本题怎么就是贪心了呢 ?
局部最优就是每次取出最大的跳跃范围,在最大跳跃范围cover范围内移动,全局最优最终整体的最大跳跃范围有没有超过了终点下标.
class Solution {
public boolean canJump(int[] nums) {
int cover = 0;
for(int i =0;i<=cover;++i) {//只能在最大跳跃范围内移动
cover = Math.max(cover,nums[i]+i);//更新最大跳跃范围
if(cover>=nums.length-1) {//最大跳跃范围,超过了终点下标,立马返回true
return true;
}
}
return false;
}
}
总结 :
又做了一道贪心,发现贪心在脑海中,就是每次取出最大->局部最优,进而整体计算完毕之后,得出的最后答案就是全局最优.
嗯... 也就是思考把一个大问题拆分成我这一步怎么走,我这一步怎么走才能达到最优呢 ? 每一步达到最优,最终的结果就是全局最优.应该可以这样理解吧,.... 还是慢慢积累题型总结吧....