这个题字节一面做过 不过当时没想到好的解法
首先能写出一个回溯的搜索算法:
class Solution {
private boolean[] vis;
private boolean dfs(int[] nums,int cur){
if(cur==nums.length-1){
return true;
}
boolean rs=false;
vis[cur]=true;
for(int i=1;i<=nums[cur];i++){
// 向右/向左
// 👆 指正,这里是不需要向左跳的,不过即使如此也过不了qaq
if(cur+i<nums.length&&!vis[cur+i]){
vis[cur+i]=true;
rs=rs||dfs(nums,cur+i);
vis[cur+i]=false;
}
}
return rs;
}
public boolean canJump(int[] nums) {
vis=new boolean[nums.length];
return dfs(nums,0);
}
}
超时
突然想到这个题很适合用dp来做:
class Solution {
public boolean canJump(int[] nums) {
// dp[i]表示从第i个位置出发,能否到达终点
// 递推公式:dp[i]=dp[i+1] || dp[i+2] || ... || dp[i+nums[i]]
boolean[] dp=new boolean[nums.length];
dp[dp.length-1]=true;
for(int i=dp.length-2;i>=0;i--){
// 从当前点,判断所有他能到达的点,看能否到达
for(int j=1;j<=nums[i];j++){
if(dp[i+j]){
dp[i]=true;
break;
}
}
}
return dp[0];
}
}
虽然挺慢的
最妙的还是这个(,虽然不是不能马上想到,这个题dp应该是能马上想到的
class Solution {
public boolean canJump(int[] nums) {
// reach表示能通过跳跃到达的最远位置
int reach=0;
for(int i=0;i<nums.length;i++){
if(i>reach){
// 当前遍历到的位置,是不能通过跳跃到达的
// 那么自然也到不了终点
return false;
}
reach=Math.max(reach,nums[i]+i);
}
// 上述循环走完,说明对于终点,也是可以通过跳跃到达
return true;
}
}