hot100—79.跳跃游戏II

答疑
问:为什么代码只需要遍历到 n−2?

答:当 i=n−2 时,如果 i<curRight,说明可以到达 n−1;如果 i=curRight,我们会造桥,这样也可以到达 n−1。所以无论是何种情况,都只需要遍历到 n−2。或者说,n−1 已经是终点了,你总不能在终点还打算造桥吧?

问:我能想出这题的思路,就是代码实现总是写不对,有没有什么建议?

答:清晰的变量名以及一些必要的注释,会对理清代码逻辑有帮助。在出现错误时,可以用一些小数据去运行你的代码,通过 print 或者打断点的方式,查看这些关键变量的值,看看是否与预期结果一致。

问:如果题目没有保证一定能到达 n−1,代码要怎么改?

答:见 1326. 灌溉花园的最少水龙头数目,我的题解。

Python3
Java
C++
C
Go
JavaScript
Rust
class Solution:
    def jump(self, nums: List[int]) -> int:
        ans = 0
        cur_right = 0  # 已建造的桥的右端点
        next_right = 0  # 下一座桥的右端点的最大值
        for i in range(len(nums) - 1):
            # 遍历的过程中,记录下一座桥的最远点
            next_right = max(next_right, i + nums[i])
            if i == cur_right:  # 无路可走,必须建桥
                cur_right = next_right  # 建桥后,最远可以到达 next_right
                ans += 1
        return ans
复杂度分析
时间复杂度:O(n)。其中 n 是 nums 的长度。
空间复杂度:O(1)。
更多相似题目,见下面贪心题单中的「区间贪心」。

分类题单
如何科学刷题?

滑动窗口与双指针(定长/不定长/单序列/双序列/三指针/分组循环)
二分算法(二分答案/最小化最大值/最大化最小值/第K小)
单调栈(基础/矩形面积/贡献法/最小字典序)
网格图(DFS/BFS/综合应用)
位运算(基础/性质/拆位/试填/恒等式/思维)
图论算法(DFS/BFS/拓扑排序/最短路/最小生成树/二分图/基环树/欧拉路径)
动态规划(入门/背包/状态机/划分/区间/状压/数位/数据结构优化/树形/博弈/概率期望)
常用数据结构(前缀和/差分/栈/队列/堆/字典树/并查集/树状数组/线段树)
数学算法(数论/组合/概率期望/博弈/计算几何/随机算法)
【本题相关】贪心与思维(基本贪心策略/反悔/区间/字典序/数学/思维/脑筋急转弯/构造)
链表、二叉树与回溯(前后指针/快慢指针/DFS/BFS/直径/LCA/一般树)
字符串(KMP/Z函数/Manacher/字符串哈希/AC自动机/后缀数组/子序列自动机)
我的题解精选(已分类)

欢迎关注 B站@灵茶山艾府

上一篇题解
详细通俗的思路分析,多解法
下一篇题解
[Python3/Java/C++/Go/TypeScript] 一题一解:贪心(清晰题解)
评论 (41)

排序:最热

评论


不啻微茫
来自 陕西
2025.04.23
优雅!

1
回复


Sarinee
来自 河南
2024.12.17
补两个“直觉上正确”的结论的说明
1,为什么走到头了才跳是对的,题意不应该是从中间某座桥的起点位置就跳吗?
因为在同一座桥上走回头路并不会让你的跳跃次数+1
在两座桥重合部分的任意一步跳都可以,都等效为往回走到下一座桥的起点,仍然只计算跳的次数+1
但没走到头的时候,你无法确定当前准备跳到的那座桥是不是能通往更远的位置
因此只有走到头、不得不跳的时候,才能确定下一步跳到哪座桥上是正确的
然后倒着往回走,走到要跳的那一座桥的起点,跳过去

2,为什么一定是跳到右端点最远的下一座桥?
假设跳的不是右端点最远(larger_next_right)的桥,而是less_next_right
那么当我走到头(less_next_right)的时候,我此时能找到的下一座桥的最远位置next_next_right
我在larger_next_right这座桥上,走到less_next_right位置时也能获取到,而且还能进一步尝试寻找更远的next_next_right
一旦less_next_right这座桥无法到达终点,而larger_next_right这座桥可以时,我就不得不多跳一次
因此选择右端点最远的桥跳是正确的
展开全部
30
展示 1 条回复
回复


要是

来自 北京
2024.12.20
如果理解了贪心,但又感觉写不出灵神这么精炼的代码,不妨看看下面这种思路的代码。

    public int jump(int[] nums) {
        int n = nums.length;
        int curL = 0, curR = 0, ans = 0; // curL: 当前可移动的左端点,curR: 当前可移动的右端点,初始时在0号位置,可以理解为移动区间为[0,0]
        while (curR < n - 1) {  // 当可移动的区间又端点没能达到nums.length-1
            int l = curL, r = curR;
            for (int i = l; i <= r; i++){ // 遍历当前可移动区间的所有位置,找到最大的右端点
                if (nums[i] + i > curR) {
                    curR = nums[i] + i; // 更新可移动区间的左端点和右端点
                    curL = i;
                }
            }
            ans++;
        }
        return ans;
    }
展开全部
14
展示 6 条回复
回复


焕、心

来自 广东
2025.01.27
c++记忆化搜索就不用证明贪心正确性了

const int INF=0x3f3f3f3f;
const int N=1e5+10;
class Solution {
    vector<int> nums;
    int f[N];
    int dfs(int index){
        if(index>=nums.size()-1)
            return 0;
        int &v=f[index];
        if(v!=INF)
            return v;
        //从当前index跳跃可以跳跃nums[index]次
        for(int i=1;i<=nums[index];i++)
            v=min(v,dfs(index+i)+1);
        return v;
    }
public:
    int jump(vector<int>& nums) {
        memset(f,0x3f,sizeof(f));
        this->nums=nums;
        int res=dfs(0);
        return res;    
    }
};
//不断暴力枚举对应跳转[0,nums[i]]这个区间的位置,然后进行一个记忆化
//可以发现时间复杂度为1e4*1000不会超时
//对应的空间定义为
展开全部
5
回复


灵茶天师府
来自 陕西
2024.09.27
新鲜的本体,抓抓抓!

16
展示 2 条回复
回复



来自 广东
2024.10.06
很热乎,发现灵神最近在补hot100的题解

14
回复


Sarinee
来自 河南
2024.12.17
如果题目不保证能跳到n-1

class Solution:
    def jump(self, nums: List[int]) -> int:
        ans = 0
        cur_right = 0  # 已建造的桥的右端点
        next_right = 0  # 下一座桥的右端点的最大值
        for i in range(len(nums) - 1):
            next_right = max(next_right, i + nums[i])
            if i == cur_right:
                if i == next_right:  # 由于next_right >= cur_right,这里就代表无法往更远处去了,因此止步于此
                    return -1  # 此时的i也是能到达的最远位置
                cur_right = next_right
                ans += 1
        return ans
展开全部
7
回复


dczv
来自 北京
2025.03.12
class Solution {
public int jump(int[] nums) {
int cur =0;
int next =0;
int ans =0;
int n = nums.length;
if(n==1)return 0;
for(int i=0;i<nums.length;i++){
next = Math.max(next,i+nums[i]);
if(i==cur){
cur =next;
ans++;
}
if(cur>=n-1)break;
}
return ans;

}
}理解不了可以到达n-2 可以设置条件跳出

展开全部

作者:灵茶山艾府
链接:https://leetcode.cn/problems/jump-game-ii/solutions/2926993/tu-jie-yi-zhang-tu-miao-dong-tiao-yue-yo-h2d4/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值