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

LeetCode 45.跳跃游戏II:贪心策略下的最少跳跃次数求解

一、问题定义与核心挑战

1.1 问题描述

给定一个非负整数数组 nums,你最初位于数组的第一个下标。数组中的每个元素 nums[i] 表示你在该位置可以跳跃的最大长度。你的目标是使用最少的跳跃次数到达数组的最后一个下标。假设你总能到达数组的最后一个下标。

1.2 核心特征与难点

  • 最优性要求:不仅要判断可达性,还要找到最少跳跃次数
  • 跳跃规则:从位置 i 可跳到 i+1i+nums[i] 之间的任意位置
  • 贪心选择:如何在每一步选择最优的跳跃点以最小化总次数

示例

  • 输入:nums = [2,3,1,1,4]
  • 输出:2(最优路径:0→1→4,两次跳跃)

二、解题思路:基于覆盖范围的贪心策略

2.1 核心思想

通过跟踪当前覆盖范围下一步最大覆盖范围,在每次到达当前覆盖范围的边界时进行跳跃,从而保证每次跳跃都是最优的:

  • 当前覆盖范围(cover):当前跳跃所能到达的最远位置
  • 下一步最大覆盖范围(maxCover):在当前覆盖范围内,所有位置能到达的最远位置
  • 跳跃时机:当遍历到当前覆盖范围的边界时,必须进行一次跳跃,此时将当前覆盖范围更新为下一步最大覆盖范围

2.2 直观理解

把跳跃过程想象成多阶段冲刺:

  1. 第一阶段:从起点出发,能到达的范围是 [0, cover],在这个范围内寻找能跳得最远的点,确定下一阶段的最大范围 maxCover
  2. 当到达第一阶段的边界(i = cover)时,必须跳一次,进入第二阶段,此时 cover 更新为 maxCover
  3. 重复上述过程,直到覆盖范围包含终点

三、代码逐行解析

3.1 边界条件处理

if (nums.length == 1) {return 0;  // 只有一个元素时,无需跳跃
}

3.2 核心变量定义

int cover = 0;       // 当前覆盖范围的边界
int maxCover = 0;    // 下一步能到达的最大覆盖范围
int cnt = 0;         // 跳跃次数

3.3 遍历与跳跃逻辑

for (int i = 0; i < nums.length; i++) {// 持续更新下一步能到达的最大覆盖范围maxCover = Math.max(i + nums[i], maxCover);// 当到达当前覆盖范围的边界,且能跳得更远时if (i == cover && maxCover > cover) {cover = maxCover;  // 更新覆盖范围cnt++;             // 跳跃次数加1// 若已覆盖终点,提前返回if (cover >= nums.length - 1) {return cnt;}}
}

3.4 返回结果

return cnt;

四、算法执行过程演示

nums = [2,3,1,1,4] 为例:

索引 i当前元素 nums[i]maxCover 计算关键操作covercnt
02max(0+2=2, 0) = 2-00
13max(1+3=4, 2) = 4-00
21max(2+1=3, 4) = 4i=2 == cover=0?不00
31max(3+1=4, 4) = 4i=3 == cover=0?不00
44max(4+4=8, 4) = 8i=4 == cover=0?是
maxCover>cover → 更新 cover=4,cnt=1
cover≥4(终点)→ 返回 1?
41

注意:实际执行中,当 i=2 时已经满足 i==cover(0),此时会触发跳跃:

  • 在 i=2 时,i==cover(0)且 maxCover=4>0 → cover=4,cnt=1
  • 此时 cover=4 已包含终点(4),直接返回 cnt=1?

修正演示:

  • i=0 时,maxCover=2
  • i=1 时,maxCover=4
  • i=2 时,i==cover(0)→ 触发跳跃,cover=4,cnt=1,此时 cover≥4 → 返回 1

最终结果为 2?不,正确结果应为 2,这里需要更精确的步骤分析:

正确步骤:

  1. 初始状态:cover=0,maxCover=0,cnt=0
  2. i=0:
    • maxCover = max(0+2, 0) = 2
    • i != cover(0==0),但需判断是否更新
    • 此时 i==cover 且 maxCover>cover → cover=2,cnt=1
  3. i=1:
    • maxCover = max(1+3=4, 2) =4
  4. i=2:
    • icover(22)
    • maxCover=4>2 → cover=4,cnt=2
    • 此时 cover≥4(终点)→ 返回 2

五、核心逻辑深度解析

5.1 为什么在 i == cover 时跳跃?

i == cover 表示已到达当前跳跃能覆盖的最远距离,此时必须进行下一次跳跃才能继续前进。选择此时跳跃能保证每次跳跃都是必要的,且跳跃范围是当前能达到的最大可能,从而最小化跳跃次数。

5.2 为什么 maxCover 能保证最优性?

maxCover 记录了当前覆盖范围内所有位置能到达的最远距离,选择这个范围作为下一次跳跃的覆盖范围,确保了每次跳跃都能到达最远的位置,从而减少总跳跃次数。

5.3 为什么无需考虑具体跳跃到哪个位置?

贪心算法的核心是“只关注范围不关注具体点”。只要知道下一次能覆盖的最大范围,就能确定最少跳跃次数,无需记录具体跳到哪个位置。

六、算法复杂度分析

  • 时间复杂度:O(n),只需遍历数组一次
  • 空间复杂度:O(1),仅使用常数个变量

七、常见误区与优化说明

7.1 误区1:在每次循环中都尝试跳跃

错误地在每个位置都进行跳跃判断,会导致跳跃次数过多。正确做法是只在到达当前覆盖范围边界时才跳跃。

7.2 误区2:忽略 maxCover > cover 的判断

如果没有这个判断,当无法跳得更远时(如 nums = [0,0,0]),会错误地增加跳跃次数。

7.3 优化点:提前终止循环

cover 已覆盖终点时,可立即返回结果,无需遍历剩余元素。

八、总结:贪心策略的跳跃优化

本题的贪心解法通过跟踪覆盖范围实现了最少跳跃次数的求解,核心在于:

  1. 区分当前覆盖范围和下一步最大覆盖范围
  2. 在适当的时机(到达当前范围边界)进行跳跃
  3. 每次跳跃都选择能到达的最远范围

这种策略确保了每一步都是最优的,从而在整体上得到最少的跳跃次数。掌握这种基于范围的贪心思想,可有效解决类似的优化路径问题。

代码的关键在于通过两个变量 covermaxCover 分别跟踪当前覆盖范围和下一步能到达的最大范围,在到达当前范围边界时进行跳跃并更新范围,从而保证每次跳跃都是最优的,最终得到最少的跳跃次数。

http://www.lryc.cn/news/624266.html

相关文章:

  • 如何在windows下使用usbview查看USB设备信息
  • 局域网视频软件BeeWorks,内网顺畅沟通
  • CloudBase AI ToolKit + VSCode Copilot:打造高效智能云端开发新体验
  • 8.19 note
  • AI心理助手开发文档
  • 《Python学习之使用标准库:从入门到实战》
  • ST05跟踪MRP的运行(MD01)过程
  • Day8--滑动窗口与双指针--1004. 最大连续1的个数 III,1658. 将 x 减到 0 的最小操作数,3641. 最长半重复子数组
  • vite+react+antd,封装公共组件并发布npm包
  • 实践笔记-VSCode与IDE同步问题解决指南;程序总是进入中断服务程序。
  • RocksDB 解密可逆哈希:BijectiveHash的设计奥秘
  • Vue diff简介
  • Rust学习笔记(六)|Rust 中的常用集合(Vector、String、HashMap)
  • MiniMax Agent 上线 Market Place ,AI一键复制克隆网站
  • 部署 HAProxy 高可用
  • python 数据拟合(线性拟合、多项式回归)
  • Android Coil3视频封面抽取封面帧存Disk缓存,Kotlin(2)
  • 云计算:企业数字化转型的核心引擎
  • Kubernetes(K8s)常用命令全解析:从基础到进阶
  • 【Kubernetes】在 K8s 上部署 Prometheus
  • C语言基础:变量与进制详解
  • K8s的命名空间需要创建吗
  • 工具集成强化学习:AI数学推理能力的新跃迁
  • Java基础(九):Object核心类深度剖析
  • 图神经网络分享系列-node2vec(二)
  • 基于51单片机WIFI心率计脉搏体温测量仪APP设计
  • HTML应用指南:利用POST请求获取全国华为旗舰店门店位置信息
  • 《若依》权限控制
  • 上下文切换及线程操作相关内容
  • 学习雪花算法