按照常规思路,已知当前元素的可跳长度,但无法知道实际该跳多少步才能达到综合最优的步数。如果选择遍历所有方案再选择最小步数太复杂。
跳跃问题的核心在于转化为求当前元素的可覆盖范围问题。每移动到一个新的位置,就更新最大的覆盖范围。直到覆盖到终点。
来看看lc的两道跳跃游戏:
https://leetcode.cn/problems/jump-game/
https://leetcode.cn/problems/jump-game-ii/
两道题的相通之处在于都是根据当前可覆盖范围决定能抵达的下标位置,再根据下标位置更新最大覆盖范围的位置。
第一题,当能覆盖到终点位置时,则说明终点位置可达。反之不可达。
class Solution {
public:
bool canJump(vector<int>& nums) {
int cover=0;
if(nums.size()==1) return true;
for(int i=0; i<=cover; i++){
cover = max(i+nums[i], cover);
if(cover >= nums.size()-1) return true;
}
return false;
}
};
第二题每当遍历再更新覆盖范围后,记录当前步数,判断是否抵达终点。由于当前起点的遍历结束,可向右移动下标位置。
class Solution {
public:
int jump(vector<int>& nums) {
if(nums.size()==1) return 0;
int depth = 0;
int cover = 0;
int begin = 0;
int max_cover = 0;
while(1){
for(int i=begin; i<=max_cover; i++){
cover = max(cover, nums[i]+i);
}
max_cover = cover;
depth++;
if(max_cover >= nums.size()-1) break;
begin ++;
}
return depth;
}
};