LeetCode-Jump Game的一种算法
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.
Example 1:
Input: [2,3,1,1,4]
Output: true
Explanation: Jump 1 step from index 0 to 1, then 3 steps to the last index.
Example 2:
Input: [3,2,1,0,4]
Output: false
Explanation: You will always arrive at index 3 no matter what. Its maximum
jump length is 0, which makes it impossible to reach the last index.
根据题意,给出一个数组,每个数组存储着一个代表该位置所能移动的长度,要求我们判断从索引为0的位置开始,能否移动到最后的位置。
如果顺着题意看,算法似乎要求我们把每一种可能都走一遍,这显得有些复杂。而实际上,如果反过来从终点开始判断,难度会降低许多。
不需要知道后面的步骤,只需要从后往前遍历,找出能够移动到终点且离终点最远的位置,记为目标位置,然后再找出能够能够移动到终点或者目标位置且离该目标位置最远的另一个位置,重新记为目标位置,依次类推,直到找到起点位置为止。
这里需要解释的是为什么要找最远的位置,其原因很简单,该算法推理是从最后一步回到第一步,假设回到上一步能够到达非最远位置,那么必然能够到达最远位置(离目标点越远意味着离起点越近),反之却不一定,因而最远位置可以看成是能否到达终点的临界点。
算法如下
class Solution {
public:
bool canJump(vector<int>& nums) {
int last = nums.size()-1, temp = last; //last为终点,temp为目标点
for (int i = last; i >= 0; i--) { //从后往前遍历
//判断i位置能否移动到目标点或者终点
if (i + nums[i] >= temp || i + nums[i] >= last) {
temp = i; //更新目标点
if (i == 0) { //若起点能移动到目标点或终点,即成功
return true;
}
}
}
return false; //否则失败
}
};
该题目难点不在于代码能力,而在于逆向思维本身。
并且由于仅采用一次循环遍历数组即可解决问题,因而其最大时间复杂度为O(n)。