原题地址
https://leetcode.com/problems/jump-game/description/
题目大意
给一个数组,数组里的数字表示从那个下标开始能往后跳的最大步数,判断能否从数组的开头跳到数组的最后一个元素。
思路
一
一开始想的就是不断地拆成更小的问题,即,由下标A跳至下标B之后,就把判断能否从下标B跳至数组最后一个元素当作一个新的更小的问题来求解。但是用了递归来写,以下写法进行了很多重复的计算
class Solution {
public:
bool canJump(vector<int>& nums) {
if(nums.empty()){
return false;
}
bool result = false;
if(nums[0]>=nums.size()-1){
return true;
}else{
for(int j = 0;j<nums[0];j++){
vector<int> sub(nums.begin()+1+j,nums.end());
if(result = canJump(sub)){
break;
}
}
}
return result;
}
};
最后超时了
二
思路一失败了之后又想了个明显有错误的解法…简单地算出每一个下标能跳到的最大下标,也就是下标和数组值相加,得到一个新数组,再遍历数组看有没有比数组最后一个元素的下标还大或者和它相等的值,有就说明能到达。
然而这种做法只要中间某一跳能跳的步数为0,并且这一跳之前的坐标的步数又都不足够越过这个停滞的点的话,就没法得到正确结果了,可能会把错的判对。
然后基于以上思路还想了一些别的按跳数为0的点对数组进行分段处理之类的操作,但是后来证明都没想全面。
三
也是最终采用的思路,从数组第一个元素开始,得到下一跳能够到达的范围(范围包括上下界,上界就是能到达的最大下标,下界就是上一跳范围之后的第一个下标),然后遍历这个范围内的元素,得到新的范围,然后对新的范围重复进行以上操作。若某次范围的上界能到达数组最后一个元素,则返回true
,若某次范围上界和上一次范围的上界相同,则返回false
。
代码
class Solution {
public:
bool canJump(vector<int>& nums) {
int old_range=0;
int next_range =0;
while(true){
int temp_next=next_range;
for(int i = old_range ; i<=next_range ; i++){
if(nums[i]+i>=temp_next){
temp_next =nums[i]+i;
if(temp_next>=(nums.size()-1)){
return true;
}
}
}
old_range = next_range+1;
if(next_range == temp_next){
break;
}
next_range = temp_next;
}
return false;
}
};