题目
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.
分析
这题和第45题很类似,所以一开始觉得会很简单。马上实现了一个最坏复杂度为O(n^2)的算法,然而超时了。超时代码为:
class Solution {
public:
bool canJump(vector<int>& nums) {
vector<bool> visit(nums.size(), false);
visit[nums.size()-1] = true;
for(int i=nums.size()-2; i>=0; i--){
for(int j = i+1; j<= i+nums[i] && j<nums.size(); j++){
if(visit[j]){
visit[i] = true;
break;
}
}
}
return visit[0];
}
};
现在考虑如何改进。主要考虑到当往后检测到一个false的值时,其包含的范围内必然都是false。通过这一点可以减少冗余计算,在最好的情况下的复杂度为O(n),在最坏的情况下的复杂度为O(n^2)
实现
class Solution {
public:
bool canJump(vector<int>& nums) {
vector<bool> visit(nums.size(), false);
visit[nums.size()-1] = true;
for(int i=nums.size()-2; i>=0; i--){
int j = i + 1;
while(j<= i+nums[i] && j<nums.size()){
if(visit[j]){
visit[i] = true;
break;
}
j += max(1, nums[j]);
}
}
return visit[0];
}
};
思考
写完之后看了别人的解法,发现还有更好的方法。从前往后扫描,不断推进能到达的最远距离,当扫描位置超过能到达的最远距离时,返回false;当能到达的最远距离覆盖重点时,返回true。代码如下:
class Solution {
public:
bool canJump(vector<int>& nums) {
vector<int> flagVec(nums.size(), 0);
int cover = 1; // max elements that we can jump to, which are either covered by previous elements, or by the current one
for (int i = 0; i < nums.size(); i++) {
if (i == nums.size() - 1) return true;
cover--;
if (nums[i] > cover) cover = nums[i];
if (cover == 0) return false;
}
return true;
}
};
网友评论