1.自己的做法,递归
class Solution {
public boolean canJump(int[] nums) {
return cJ(nums,0);
}
public boolean cJ(int[] nums,int begin){
int max=0,pos=begin;
for(int i=begin+1;i<nums.length&&i<=begin+nums[begin];i++){
if(nums[i]+i>max){
max=nums[i]+i;
pos=i;
}
}
if(pos==nums.length-1){
return true;
}else if(pos==begin){
return false;
}else{
return cJ(nums,pos);
}
}
}
这个题用的是贪心算法的思想,每次begin的选择都是在目前的选择下做出最优的选择
begin从0开始,在这里用一个例子来说明
[2,3,1,5,4,0,0,0,0,1]
1.此时,begin=0,nums[i]=2,这意味着你可以调到i=1和i=2的位置,也就是begin+nums[begin]
这就是判断条件i<=begin+nums[begin]的来历
2.此时,你只要选择i<=begin+nums[begin],在这个范围内,哪个位置作为下个位置的起跳点,此时,你当然是选择最远的最好了对不对?
但是,当时我纠结一个点,我可以从3跳到4,也可以从1跳到5,当时我自己把自己禁锢住了,就一股脑的觉得每次就要跳nums[i],但是其实从3也可以跳到5,不知道有没有人会和我一样犯糊涂
3.还有一个问题,是在最后return时,pos==nums.length-1和pos==begin的先后问题,我原来不是这样放,是pos==begin放在最前面,我当时觉得,如果最后pos==begin,证明它没法往下跳了,但是如果数组为[0]呢
其实这时候就已经成功了,pos==nums.length-1的同时pos==begin
下面又优化了一下判断条件,如果可以从begin跳到最后,就不进循环了,浪费时间
class Solution {
public boolean canJump(int[] nums) {
return cJ(nums,0);
}
public boolean cJ(int[] nums,int begin){
if(begin+nums[begin]>=nums.length-1) return true;
int max=0,pos=begin;
for(int i=begin+1;i<nums.length&&i<=begin+nums[begin];i++){
if(nums[i]+i>max){
max=nums[i]+i;
pos=i;
}
}
if(pos==begin){
return false;
}else{
return cJ(nums,pos);
}
}
}
class Solution {
public boolean canJump(int[] nums) {
int max,pos;
for(int i=0;i<nums.length;i=pos){
max=0;
pos=i;
for(int j=i+1;j<nums.length&&j<=i+nums[i];j++){
if(nums[j]+j>max){
max=nums[j]+j;
pos=j;
}
}
if(pos==nums.length-1){
return true;
}else if(pos==i){
return false;
}
}
return false;
}
}
一样的贪心算法,就是优化了一下,牺牲时间,提高空间
2.看了官方题解,感觉自己想的有点复杂,哎,太蠢了
class Solution {
public boolean canJump(int[] nums) {
int max=0;
for(int i=0;i<nums.length;i++){
if(i<=max){
max=Math.max(max,nums[i]+i);
if(max>=nums.length-1) return true;
}
}
return false;
}
}
这个max,就是可以跳到的最远的地方,我感觉我的递归为啥比这个用时少?可能体现在那个中间return false上了