问题来源
问题描述
Given an array of non-negative integers, you are initially positioned at the first index of the array.
Each element in the array represents your maximum jump length at that position.
Determine if you are able to reach the last index.
For example:
A = [2,3,1,1,4], return true.
A = [3,2,1,0,4], return false.
问题分析
最开始做这道题目,第一个想法就是递归,因为显然每一步的操作都是类似的,在第i个元素时,走[0, A[i]]步。于是写了第一版递归代码:
class Solution {
public:
int end;
bool flag = false;
vector<int> m;
bool canJump(vector<int>& nums) {
m = nums;
end = m.size()-1;
jump(0);
return flag;
}
void jump(int start) {
if (start == end) {
flag = true;
return;
}
for (int i = 1; i <= m[start]; i++) {
if (start+i > end) return;
dfs(start+i);
if (flag == true) return;
}
}
};
然而却超时了。因为测例中有一个比较大的输入
[25000,24999,24998,24997,24996,24995,24994,24993,24992...
于是不得不改变方法。重新思考问题,假设我们能够走到终点,那么,显然我们能够从终点逆推回起点。但是一个问题是,怎么逆推?假设终点坐标为last,那么,在last之前,必然存在有一个点,该点的下标加上该点能走的步数,必然是大于等于last。遵循这个思路,每次找到一个这样的点时,我们便将其更新为last的值,而显然,最终只要last等于0,那么就可以到达,否则不行。
解决代码
class Solution {
public:
bool canJump(vector<int>& nums) {
int n = nums.size();
int last = n-1;
for (int i = n-2; i >= 0; i--)
if (nums[i]+i >= last) last = i;
return last == 0;
}
};