![这里写图片描述](https://img-blog.csdn.net/20171129184642315)
题目的要求是给出一个数组,数组中每个元素的数值代表可以从这个下标“跳跃”到的最大距离(注意是最大,也就是说可以跳小于这个距离)。初始下标是0,问能否跳到数组最大的下标。
其实第一眼看到这道题,我以为是要用分治算法或者构建一棵树之类的,讲真,用树真的可以做的好吗……后来我的想法是,从下标0开始,记录它能到达的所有下标,然后再按顺序访问这些下标,看它们能跳转到哪里,能否跳转到最大的下标。所以我一开始采用了set来存储,利用set元素的唯一性,把能到的下标都插进去,直到能够跳到最后或者set遍历完还没到最后,结果75个测试中恰恰有个巨长的测试会超时,其他都通过。明显我的想法虽然离目标不远,但还是太复杂了。于是我决定每次插入前先判断能否使得set中元素增加(能到达的最大下标增大),不能就不处理了。于是我第一次pass了这道题,但只超过了9%的提交,明显有待改进。
以下是第一次成功的代码,仅仅是留个纪念,因为后面的方法更简洁
class Solution {
public:
bool canJump(vector<int>& nums) {
int asize = nums.size();
if (asize == 0) return false;
if (asize == 1) return true;
set<int> myset;
myset.insert(0);
set<int>::iterator it = myset.begin();
int max = 0;
while(it != myset.end()) {
if (max >= asize - 1) return true;
int diff = *it + nums[*it] - max;
if (diff > 0) {
for (int i = 1; i <= diff; i++) {
myset.insert(max + i);
}
max = *it + nums[*it];
}
it++;
}
return false;
}
};
为了寻求更快速的方法,我查看了讨论区,并且发现我把能到达的元素全部记录起来完全是多余的,因为能跳到的最大下标之前的所有下标都是可达的,所以只记录当前最大下标就行了。于是简化之后,超过了82.74%的提交。
改进后的代码如下:
class Solution {
public:
bool canJump(vector<int>& nums) {
int asize = nums.size();
int reach = 0;
int i = 0;
for (i = 0; i < asize&&i <= reach; i++) {
if (i + nums[i] > reach) {
reach = i + nums[i];
}
}
return i == asize;
}
};