45.跳跃游戏 II
给定一个非负整数数组,你最初位于数组的第一个位置。
数组中的每个元素代表你在该位置可以跳跃的最大长度。
你的目标是使用最少的跳跃次数到达数组的最后一个位置。
示例:
- 输入: [2,3,1,1,4]
- 输出: 2
- 解释: 跳到最后一个位置的最小跳跃数是 2。从下标为 0 跳到下标为 1 的位置,跳 1 步,然后跳 3 步到达数组的最后一个位置。
说明: 假设你总是可以到达数组的最后一个位置。
本题和跳跃游戏|有共同之处,都是通过记录最大覆盖范围来判断什么时候走到尽头了,但个人认为本题的难点在于如何完成整个过程,和何时让result++,一开始我是想用回溯走完所有过程,result每次取最小值,最后返回,但发现有很多不足之处:
-
复杂度高:回溯算法通常会枚举所有可能的跳跃路径,这在问题规模较大时会导致指数级的时间复杂度,性能非常低效。
-
无法保证最优解:回溯算法找到的是所有可能的解中的一个,而不是一定是最少跳跃次数的解。
-
无法有效剪枝:即使使用回溯,也需要额外的优化措施来剪枝,以防止搜索过多不必要的路径,但这往往很难实现。
后来才知道贪心怎么做:
那本题贪在哪?其实是每次尽量走的最远,即循环里i每走一步,就记录一下能到的最远距离,当最远距离到达最后一位时则说明成功了,可以返回result了
那么什么时候result++呢?
class Solution {
public:
int jump(vector<int>& nums) {
int cur = 0;//用来记录当前可走的范围
int result = 0;
int next = 0;
for(int i = 0 ;i<nums.size();i++){
next = max(i + nums[i],next);
if(i == cur){//当走到界限时,需要走一步,同更新当前范围至最大范围。
if(cur != nums.size()-1){
result++;
cur = next;
}
}
if(cur == nums.size()-1) break;
}
return result;
}
};
其实并不是每走一步就加一次,而是当超过该次能走的最大范围时才+1,可以这么想,既然我都可以直接一步到位,我为什么要每步都加,当i走到临界点时,判断该点是否是最末尾的位置,如果不是则result++(走一步),然后将前面记录的最大距离next赋值给cur,更新当前能走到的最远距离。(cur的设立是关键)最后如果 满足条件则返回result即可。