当前位置: 首页 > backend >正文

【LeetCode 热题 100】45. 跳跃游戏 II

Problem: 45. 跳跃游戏 II
给定一个长度为 n 的 0 索引整数数组 nums。初始位置为 nums[0]。
每个元素 nums[i] 表示从索引 i 向后跳转的最大长度。换句话说,如果你在索引 i 处,你可以跳转到任意 (i + j) 处:
0 <= j <= nums[i] 且
i + j < n
返回到达 n - 1 的最小跳跃次数。测试用例保证可以到达 n - 1。

文章目录

  • 整体思路
  • 完整代码
  • 时空复杂度
    • 时间复杂度:O(N)
    • 空间复杂度:O(1)

整体思路

这段代码旨在解决经典的 “跳跃游戏 II” (Jump Game II) 问题。与判断“能否到达”的第一代问题不同,此问题要求在假设总能到达终点的前提下,计算出到达数组最后一个位置所需的 最小跳跃次数

该算法采用了一种非常高效的 贪心算法,其思想可以类比为 广度优先搜索 (BFS)。它不是关注每一步具体跳到哪里,而是在每一“跳”的范围内,寻找下一“跳”能到达的最远距离。

算法的逻辑步骤如下:

  1. 定义边界

    • 算法使用两个核心变量来定义跳跃的边界:
      • curRight当前这一跳所能到达的最远边界。可以理解为 BFS 中当前层的右边界。
      • nxtRight:从当前层(0curRight 之间的所有位置)出发,下一跳所能到达的最远边界。
    • ans 变量用于累计跳跃的次数。
  2. 贪心遍历

    • 算法通过一个 for 循环遍历数组。循环的终止条件是 i < nums.length - 1,这一点非常关键,因为我们只需要考虑从倒数第二个位置(或之前)起跳的情况,一旦到达或越过最后一个位置,就不需要再跳了。
    • 在当前跳跃范围内寻找最优的下一步:在循环的每一步(i0curRight),我们都在当前可达的范围内。对于每个位置 i,我们计算从它出发能跳到的最远距离 nums[i] + i。然后,我们用这个值去贪心地更新 nxtRight (nxtRight = Math.max(nxtRight, nums[i] + i))。这确保了 nxtRight 始终记录着从当前这一跳的覆盖范围内,能为下一跳创造的最远落点。
    • 执行跳跃:当循环变量 i 到达了 curRight 的边界时,意味着我们已经遍历完了当前这一跳能到达的所有位置。此时,我们必须执行一次跳跃才能继续前进。
      • if (i == curRight) 这个条件就是“执行跳跃”的触发器。
      • 当触发时,我们将 curRight 更新为 nxtRight,这相当于进入了 BFS 的下一层,设定了新的、更远的可达边界。
      • 同时,我们将跳跃次数 ans 加一。
  3. 返回结果

    • 当循环结束时,ans 中就记录了到达终点所需的最小跳跃次数。

完整代码

class Solution {/*** 计算到达数组最后一个位置所需的最小跳跃次数。* @param nums 数组,每个元素代表在该位置的最大跳跃长度。* @return 最小跳跃次数*/public int jump(int[] nums) {// curRight: 当前这一跳能够到达的最远右边界。int curRight = 0;// nxtRight: 在当前跳跃的覆盖范围内,下一步能够到达的最远右边界。int nxtRight = 0;// ans: 记录跳跃的次数,即结果。int ans = 0;// 遍历数组。循环到倒数第二个元素即可,因为我们的目标是“到达”最后一个位置,// 而不是从最后一个位置起跳。for (int i = 0; i < nums.length - 1; i++) {// 贪心选择:更新下一步能到达的最远距离。// 在当前跳跃的可达范围内(i 从 0 到 curRight),// 我们不断计算从每个位置 i 出发能跳到的最远点 (nums[i] + i),// 并用它来更新 nxtRight。nxtRight = Math.max(nxtRight, nums[i] + i);// 触发跳跃的条件:当 i 到达了当前跳跃的边界。// 这意味着我们已经考察完了当前这一跳能到达的所有位置,// 必须进行一次新的跳跃才能继续前进。if (i == curRight) {// 更新当前跳跃的边界为下一步能到达的最远边界。curRight = nxtRight;// 跳跃次数加一。ans++;}}// 循环结束后,ans 即为最小跳跃次数。return ans;}
}

时空复杂度

时间复杂度:O(N)

  1. 循环:算法的核心是一个 for 循环,它从 i = 0 遍历到 nums.length - 2。这个循环最多执行 N-1 次,其中 Nnums 数组的长度。
  2. 循环内部操作
    • 在循环的每一次迭代中,执行的都是基本的 Math.max、加法、比较和赋值操作。
    • 这些操作的时间复杂度都是 O(1)

综合分析
算法由 N-1 次 O(1) 的操作组成。因此,总的时间复杂度是 (N-1) * O(1) = O(N)

空间复杂度:O(1)

  1. 主要存储开销:算法只使用了几个固定数量的整型变量(curRight, nxtRight, ans, i)。
  2. 空间大小:这些变量的数量不随输入数组 nums 的大小 N 而改变。

综合分析
算法没有使用任何与输入规模 N 成比例的额外数据结构(如新数组或哈希表)。因此,其额外辅助空间复杂度为 O(1)

参考灵神

http://www.xdnf.cn/news/17875.html

相关文章:

  • 杭州网站建设:如何展示企业科研实力?
  • GitCode疑难问题诊疗
  • 状态流程框架(cola-component-statemachine)
  • 正点原子STM32H743配置 SDRAM
  • 序列晋升6:ElasticSearch深度解析,万字拆解
  • 【补充】数据库中有关系统编码和校验规则的简述
  • 非极大值抑制(NMS)详解:目标检测中的“去重神器”
  • 小兔鲜儿-小程序uni-app(二)
  • 【原创理论】Stochastic Coupled Dyadic System (SCDS):一个用于两性关系动力学建模的随机耦合系统框架
  • C语言基础00——基本补充(#define)
  • 非中文语音视频自动生成中文字幕的完整实现方案
  • 38 C++ STL模板库7-迭代器
  • 电子电气架构 --- 线束设计一些事宜
  • 商城开发中,有哪些需要关注的网络安全问题
  • 【大模型微调系列-02】 深度学习与大模型初识
  • tun/tap 转发性能优化
  • 如何通过ETLCloud做数据监听
  • 北京JAVA基础面试30天打卡10
  • Unity与OpenGL中的材质系统详解
  • 电子电气架构 --- 探索软件定义汽车(SDV)的技术革新
  • 力扣326:3的幂
  • Ubuntu20.04下Px4使用UORB发布消息
  • OpenCV-循环读取视频帧,对每一帧进行处理
  • Qt——常用Widget(控件)
  • 【swift】SwiftUI动画卡顿全解:GeometryReader滥用检测与Canvas绘制替代方案
  • 有红帽认证证书可以0元置换华为openEuler-HCIA/HCIP认证
  • 醋酸镧:看不见的科技助力
  • 介绍TCP的拥塞控制
  • Oracle EBS R12.2 adlnkoh.sh执行报错
  • windows系统创建FTP服务