1.从后往前暴力
首先考虑数组中只有一个元素的情况,直接返回true
当数组元素大于等于2个时,我们从后往前遍历,使用双指针,i,j,寻找能够到达最后一个位置的的元素;
1)j指向倒数第一个元素,i指向倒数第二个元素,寻找能够到达最后一个位置的元素
2)如果nums[i]+i>=j,则说明可以从i到达j,此时只要能够到达i,一定可以到达j,则将j指向i,i指向j-1,即j=i,i=j-1,
如果不行,则j不变,i左移,继续寻找,直到结束或找到。
3)然后继续寻找能够到达j的位置i,进入下一轮
终止条件是i>0&&j>0
跳出循环之后判断nums[i]+i>=j是否成立,成立则返回true
代码如下:
class Solution {
public:
bool canJump(vector<int>& nums) {
//双指针,
int len=nums.size();
if(len==1)
return true;
int i=len-2,j=len-1;
while(i>0&&j>0)
{
if(nums[i]+i>=j)//从i能到j
{
j=i;
i=j-1;
}
else
i--;
}
if(nums[i]+i>=j)
return true;
return false;
}
};
2.仍然从后往前遍历
不设两个指针,如果能够到达当前的终点,则截取点后面的元素
代码如下:
class Solution {
public:
bool canJump(vector<int>& nums) {
//判断能否到达最后一个位置,从倒数第二个开始往前遍历,步长为1,若当前元素值能到达
int n=1;
for(int i=nums.size()-2;i>=0;i--){
if(nums[i]>=n)
n=1;//如果能够到达当前的终点,则nums[i]成为新的终点,步长为1
else
n++;//步长增加
if(i==0&&n>1) //到达第一个,且第一个无法到达当前的终点(如果能到达,则n将为1)
return false;
}
return true;
}
};
3.贪心
对于数组中任意一个位置j,只要存在一个位置i,位置i可到达且i+nums[i]>=j,则j就是可到达的
即对于可到达的位置i,i+1,i+2,...i+nums[i].都是可到达的
因此,从数组第一个位置出发,依次遍历数组中每一个位置的元素,且实时维护最远可以到达的位置。对于当前遍历到的位置i,如果它在最远可到达的位置范围内,则我们就可以从起点通过若干次跳跃到达该位置,故使用i+nums[i]更新最远可达的位置
在遍历的过程中,如果最远可达的位置大于等于数组最后一个元素的位置,则最后一个位置可达,
代码如下:
class Solution {
public:
bool canJump(vector<int>& nums) {
int len=nums.size();
if(len<=1)
return true;
int maxDis=nums[0];
for(int i=0;i<len;i++)
{
if(i<=maxDis)
maxDis=max(maxDis,nums[i]+i);
}
return maxDis>=len-1;
}
};