如题
一眼看上去最直观肯定就是递归了,那就安排
public static boolean canJump(int[] nums) {
if(nums==null||nums.length==0) {
return false;
}else if(nums.length==1) {
return true;
}
return canJum(nums,0);
}
public static boolean canJum(int[]nums,int i) {
int num=nums[i];
if(i+num>=nums.length-1) {
return true;
}
if(num==0) {
return false;
}
boolean b=false;
for(int m=1;m<=num;m++) {
b=b||canJum(nums,i+m);
}
return b;
}
很直观的写法,也是不出意外的结果
很显然,当中做了很多的重复运算,那么我们是否可以去除这些重复运算呢,很显然可以的
public static boolean canJum1(int[]nums,int i) {
int num=nums[i];
if(i+num>=nums.length-1) {
return true;
}
if(num==0) {
return false;
}
nums[i]=0; //第一次参与运算后归0 后续可直接退出
boolean b=false;
for(int m=1;m<=num;m++) {
b=b||canJum(nums,i+m);
}
return b;
}
好了,可以通过了
但是这个效率肯定不行。既然已经想到记录已经走过的点,那么不用递归也能实现啊。譬如nums[0]=3;那么一直到0,可达的最大index为0+3。然后我们对1到3范围进行判断,假设其中nums[2]=3,2+3为该段最大值,那么我们就重复判断起始3,最大5的段。退出条件很显然,可达>=nums的最大index,期间若是起始index与最大可达相等,则为无法继续向后跳转。
public static boolean canJump2(int[] nums) {
if(nums==null||nums.length==0) {
return false;
}
int st = 0; //某一段起始index
int max = st+nums[st]; //到到此index时可达的最大index
if(max>nums.length-1) {
return true;
}
while (max>st) {
int m=max;
for(int i =st+1;i<=m;i++) { //对于当前段进行遍历,更新可达
max=Math.max(max, i+nums[i]);
}
if(max>=nums.length-1) {
return true;
}
st=m;
}
return false;
}
结果
大大进步了,但是还能进一步,既然关注的是可达的最大index,并不需要分段,那么很显然的可以直接循环实现
public static boolean canJump3(int[] nums) {
if(nums==null||nums.length==0) {
return false;
}
int max = nums[0]; //可达index
for(int i=0;i<=nums.length-1;i++) {
if(max>=nums.length-1) {
return true;
}else if(max<i) { //前序可达小于当前index,即当前index不可达
return false;
}
if(i+nums[i]>max) {
max=i+nums[i];
}
}
return true;
}
结果可以了

博客讨论了LeetCode第55题‘跳跃游戏II’的解决方案,从最初的递归思路出发,分析其效率问题。接着提出通过记录已走过的位置来避免重复运算,从而优化递归解法。最后,实现了一个无需递归的循环解法,显著提高了效率。
822

被折叠的 条评论
为什么被折叠?



