给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
判断你是否能够到达最后一个位置。
示例 1:
输入: [2,3,1,1,4]
输出: true
解释: 我们可以先跳 1 步,从位置 0 到达 位置 1, 然后再从位置 1 跳 3 步到达最后一个位置。
示例 2:
输入: [3,2,1,0,4]
输出: false
解释: 无论怎样,你总会到达索引为 3 的位置。但该位置的最大跳跃长度是 0 , 所以你永远不可能到达最后一个位置。
分析:
方法一:
看到该题时,刚开始想的是动态规划,开一个dp[]数组存储每个位置i是否能够到达,但是这样涉及到了很多重复计算,时间复杂度为n^2,运行太慢,这里贴上代码,仅供参考
class Solution {
public boolean canJump(int[] nums) {
//动态规划
boolean dp[] = new boolean[nums.length];
dp[0] = true;
//初始在第一个位置
for(int i = 0;i < nums.length;i++){
if(dp[i] == true){
int n = nums[i];
for(int j = 1;j <=n;j++){
if(i + j < nums.length){
dp[i + j] = true;
}
}
}
}
return dp[nums.length -1 ];
}
}
方法二:本题应该使用的是贪心,很重要的一点是,对于当前位置i如果可以到达,那么i+nums[i]就是当前结点能够到达的最远距离,那么小于i+nums[i]的位置也都能到达,因此我们维护一个全局变量,存储能够到达的最远距离,如果最这个maxDis大于等于数组最后一个元素,说明可以达到终点。
代码如下
class Solution {
public boolean canJump(int[] nums) {
//贪心做法
//实时维护一个全局的最远可以达到的变量
int maxDis = 0;
int n = nums.length - 1;
for(int i = 0; i < nums.length;i++){
//说明当前位置i是能够到达的
if(i <= maxDis){
int maxi = i + nums[i];//这是i这个位置能够达到的最远距离
//判断当前能够到达的最远距离是否需要更新
if(maxi > maxDis){
maxDis = maxi;
}
}
}
return maxDis >= n;
}
}