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.
对上面的数据,使用示意图帮助理解:
根据题目要求,数组里的每个元素表示从该位置可以跳出的最远距离,要求问从第一个元素(index=0)开始,能否达到数组的最后一个元素,这里认为最后一个元素为终点。需要注意一下几点:
本题可以用动态规划的思想去做,考察每个位置能达到的最远距离。第k个元素能达到的最远距离,可能为:
遍历数组元素的最远距离,使用最远距离判断能否跳到终点,思路如下:
程序最多只要遍历一遍就可以得到结果,因此时间复杂度为
代码如下:
class Solution {
public:
bool canJump(vector<int>& nums) {
if (!nums.size())
return false;
int max = nums[0];
for (int i = 1; i != nums.size(); ++i)
{
if (i > max)
return false;
else if (nums[i] + i >= nums.size() - 1)
return true;
else if (nums[i] + i > max)
max = nums[i] + i;
}
return true;
}
};
在做完本题的时候我查找了一下相关资料,之前就有其他博客说明,本题为一道非常经典的动态规划题目,可惜我还没有系统学习过动态规划,因此在刚开始看到本题的时候,没有使用动态规划的直觉,饶了好大一个弯才想到了上面的解法。
最初的想法是,既然数组中的元素均非负,则只要元素值全部为正,便一定可以达到终点。而无法达到终点的原因就是数组中的0元素,我们可以认为数组中某些位置的0元素相当于一个吸收态,元素跳到该位置就无法前进了。例如上图中的第二个例子,因此在程序中判断0是否为吸收态就可以判断能否达到终点了。
吸收态的判断方法为:若数组中0元素之前的所有元素跳过的距离均不超过0,则0为吸收态。
根据这个思路,我们可以进行正向和反向遍历,寻找吸收态。
class Solution {
public:
bool canJump(vector<int>& nums) {
if (!nums.size())
return false;
int i = 0;
while (i < nums.size() - 1)
{
if (nums[i] == 0)
{
int j = i - 1;
while (i < nums.size() - 1 && !nums[i])
i++;
i--;
bool flag = false;
while (j >= 0)
{
if (nums[j] + j >= nums.size() - 1)
return true;
else if (nums[j] + j > i)
{
i = nums[j] + j;
flag = true;
break;
}
j--;
}
if (!flag)
return false;
}
else
{
i = i + nums[i];
}
}
return true;
}
};
class Solution {
public:
bool canJump(vector<int>& nums) {
if (!nums.size())
return false;
if (nums.size() == 1)
return true;
int i = nums.size() - 1;
for (int i = nums.size() - 1; i >= 0; --i)
{
if (nums[i] == 0)
{
int j = i - 1;
bool flag = false;
while (j >= 0)
{
if ((i == nums.size()-1 && nums[j]+j ==i ) || nums[j] + j > i)
{
flag = true;
i = j + 1;
break;
}
j--;
}
if (!flag)
return false;
}
}
return true;
}
};
后面的另类解法和动态规划解法相比,动态规划的解法真是优雅啊,思路清晰明了,编写代码的过程也很愉快,不得不感叹要好好学习算法。MIT《算法导论》公开课的老师在第一节课就说过,要编写好的程序,可以两年内每天都写代码,或者你可以选一门算法课,真的很有道理呢。
LeetCode (23) Jump Game (动态规划)
原文地址:http://blog.csdn.net/angelazy/article/details/45250763