leetcode 45 Jump Game II
题目描述如下
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.
Your goal is to reach the last index in the minimum number of jumps.
Example:
Input: [2,3,1,1,4]
Output: 2
Explanation: The minimum number of jumps to reach the last index is 2.
Jump 1 step from index 0 to 1, then 3 steps to the last index.
Note:
You can assume that you can always reach the last index.
首先这道题我们可以先看下leetcode 55: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.
这道题看上去很复杂,因为从一个点出去有很多种可能性,看起来可能要用到广搜深搜之类的搜索算法,但是其实仔细一想这就是一个贪心问题,对于任意的[a0…ak]这个序列我们都可以找到一个最远可以到达的点,而如果这个点是ak的话自然就不能继续往下走了,所以这题的思路就是按顺序遍历数组中的每一个元素,计算目前的最远点,然后判断中间有没有走不下去的时候即可,代码如下:
class Solution {
public:
bool canJump(vector<int>& nums) {
int cur = 0;
for(int i = 0; i < nums.size(); i++){
cur = max(cur, i + nums[i]);
if(cur < i + 1 && i != nums.size() - 1)
return false;
}
return true;
}
};
再回到这道题的变种,这道题和上题很像,但是把判断是否能到达最后一个点换成了最短路径,我一开始觉得和上面一样的做就可以了,只需在每一次cur改变的时候增加步数就好了,但是后面交上去看到错误的样例才发现其实这样找的并不是最短的路径,比如[7,0,9,6,9,6,1,7,9,0,1,2,9,0,3]这个样例,虽然第三个点的9能比第一个点的7走的更远,但实际上7直接走到nums[7],然后nums[7]直接就可以到终点,这样实际上是没有必要走到9的,所以正确的修改思路应该是再维护一个变量保存“某个阶段”找到的最远点,而在这个阶段中找到的其他点其实可以忽略,这样让更新最远点的次数尽量少,同样也对应步数尽量少,代码如下:
class Solution {
public:
int jump(vector<int>& nums) {
int cur = 0,ans = 0,maxPos = 0;
for(int i = 0; i < nums.size(); i++){
if(maxPos >= nums.size() - 1){
break;
}
if( i + nums[i] > cur){
cur = i + nums[i];
}
if(i == maxPos){
maxPos = cur;
ans++;
}
}
return ans;
}
};
代码时间复杂度很明显是O(n)
总之这两道题主要就是要意识到这是一个贪心算法的题,虽然在leetcode里面是hard的题但是其实思路并不是太难想。