题目
https://leetcode.cn/problems/jump-game-ii/
解题过程
解法1
首先,这道题我想到了用map来解决,其实整型数组也可以,但还要考虑长度的问题有点麻烦就算了(其实就是懒)
class Solution {
public:
int jump(vector<int>& nums) {
int l = nums.size();
if(l==1) return 0;
int cnt=0,pos=0;//cnt为跳跃次数,pos为当前位置
unordered_map<int,int> pre,flag;
//pre[cnt]为上一跳后选择的下一个最优结点,
//flag为pre[cnt]结点所能到达的最远距离
//(也是截至到当前结点的最远距离)
//pre与flag一一对应
pre[0]=0,flag[0]=pre[0]+nums[0];
if(flag[0]>=l-1) return cnt+1;
pos++,cnt++;
while(pos<l){
if(pos>flag[cnt-1]) cnt++;
int dis=pos+nums[pos];
if(dis>=nums.size()-1) break;
if(dis>flag[cnt]){
pre[cnt]=pos;
flag[cnt]=dis;
}
pos++;
}
return cnt+1;
}
};
这个解法看着很乱,我大致解释一下,就是pre每一层存储的都是上一条的最优结点,flag是其对应的最远距离。如果超出了上一条的最大辐射范围,就开启一次新的跳跃。
但是,这个思路完全不需要map或者数组,其实只需要维护几个整型变量即可,所以就有了解法2
解法2
class Solution {
public:
int jump(vector<int>& nums) {
int l = nums.size();
if(l==1) return 0;
int cnt=0,pos=0;//cnt为跳跃次数,pos为当前位置
int pre,flag,t1=0,t2=0;
//pre为上一跳的最优结点,flag为pre结点所能到达的最远距离
//t1为当前跳跃的最优结点,t2为t1结点所能到达的最远距离
pre=0,flag=pre+nums[0];
if(flag>=l-1) return cnt+1;
pos++,cnt++;
while(pos<l){
if(pos>flag) { //超出上一跳最远范围,更新参数
cnt++;
pre=t1;
flag=t2;
t1=0;
t2=0;
}
int dis=pos+nums[pos];
if(dis>=nums.size()-1) break;
if(dis>t2){ // 选取这一跳的最优结点
t1=pos;
t2=dis;
}
pos++;
}
return cnt+1;
}
};
具体的解释我都放在注释里了,但还是好长啊,根本没有大佬那种几行代码解决问题的快感,于是我去题解里学习了一下,果然发现了大佬,其实思路和Jump Game很像。
解法3
作者:ikaruga
链接:https://leetcode.cn/problems/jump-game-ii/solution/45-by-ikaruga/
来源:力扣(LeetCode)
class Solution {
public:
int jump(vector<int>& nums) {
int cnt=0,last=0,flag=0;
for(int i=0;i<nums.size()-1;i++){
flag=max(flag,i+nums[i]);
if(i==last){
last=flag;
cnt++;
if(flag>=nums.size()-1) break;//我多加了一行代码,提前退出节省时间
}
}
return cnt;
}
};
其实大佬的核心逻辑很像层次遍历,关键代码就是if (i == end),这其实就是层次遍历中对层尾的判断,牛!