news 2026/9/28 3:39:31

贪心算法专题(六):步步为营的极速狂飙——「跳跃游戏 II」

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
贪心算法专题(六):步步为营的极速狂飙——「跳跃游戏 II」

哈喽各位,我是前端小L。

欢迎来到贪心算法专题第六篇! 这道题是跳跃游戏的进阶版。想象一下,你还是要从起点跳到终点,但这次我们要比拼速度(步数)。 关键在于:什么时候进行“下一次跳跃”?

比如[2, 3, 1, 1, 4]。

  • 起点是2,覆盖范围是下标1~2。

  • 我们是跳到下标1(数值3)好呢,还是跳到下标2(数值1)好呢?

    • 如果跳到1,下一跳最远能到1+3=4。

    • 如果跳到2,下一跳最远能到2+1=3。

  • 贪心策略:显然应该选下标1作为中间跳板,因为它能带我们去更远的地方!

力扣 45. 跳跃游戏 II

https://leetcode.cn/problems/jump-game-ii/

题目分析:

  • 输入:非负整数数组nums。

  • 保证:可以到达nums[n-1]。

  • 目标:最小跳跃次数。

核心思维:维护当前步数的“边界”

我们需要两个关键变量来记录覆盖范围:

  1. curDistance:当前这一步最远能覆盖到的位置。

  2. nextDistance:如果再多跳一步,最远能覆盖到的位置。

逻辑推演:我们遍历每一个位置i:

  • 在遍历过程中,不断计算并更新nextDistance = max(nextDistance, i + nums[i])。这代表“如果我在当前范围内找一个跳板,它最远能送我去哪”。

  • 当i走到了curDistance(也就是走到了当前这一步的边界):

    • 说明这一步的潜力耗尽了,我们必须进行下一次跳跃了。

    • 此时,steps++。

    • 将curDistance更新为nextDistance(把边界推得更远)。

    • 检查新的curDistance是否覆盖了终点,如果覆盖了,直接结束。

[Image visualization: Current reach boundary vs Next reach boundary]

贪心策略:不用纠结具体跳到哪个格子,我只关心**“在当前这一步的范围内,我能蓄力到的最远下一跳边界在哪里”**。当走到当前边界时,果断切换到下一跳的边界。

算法流程

  1. 如果数组长度为 1,直接返回 0(不用跳)。

  2. 初始化:

    • curDistance = 0

    • nextDistance = 0

    • steps = 0

  3. 遍历i从0到nums.size() - 2:

    • 注意:这里只需要遍历到倒数第二个元素!

    • 原因:如果我们在倒数第二个位置(或之前)更新了边界,且这个边界已经覆盖了终点,那步数就已经加了。遍历最后一个元素没有意义(我们已经在终点了,不需要再起跳)。

  4. 在循环中:

    • 更新nextDistance = max(nextDistance, i + nums[i])。

    • 如果i == curDistance:

      • 需要走下一步了:steps++。

      • 更新边界:curDistance = nextDistance。

      • 剪枝:如果curDistance >= nums.size() - 1,直接break(虽然题目保证能到,但加上这个判断逻辑更严谨)。

代码实现 (C++)

C++

#include <vector> #include <algorithm> using namespace std; class Solution { public: int jump(vector<int>& nums) { if (nums.size() == 1) return 0; int curDistance = 0; // 当前覆盖的最远距离下标 int nextDistance = 0; // 下一步覆盖的最远距离下标 int steps = 0; // 记录走的最大步数 // 关键点:只遍历到 nums.size() - 2 // 因为如果走到倒数第二个还没结束,意味着一定需要再跳一步才能到终点 // 如果遍历到 nums.size() - 1,可能会多增加一次不必要的步数 for (int i = 0; i < nums.size() - 1; i++) { // 贪心:在当前覆盖范围内,寻找能跳得最远的下一次位置 nextDistance = max(nextDistance, i + nums[i]); // 如果走到了当前步数的边界 if (i == curDistance) { steps++; // 必须再跳一步 curDistance = nextDistance; // 更新边界 // 如果新的边界已经覆盖了终点,提前结束 if (curDistance >= nums.size() - 1) { break; } } } return steps; } };

深度辨析:为什么循环只到size - 2?

这是一个容易出错的边界条件。 假设nums = [2, 1]。

  • i = 0,curDistance初始为 0。i == curDistance,触发更新:

    • steps变成 1。

    • curDistance变成0+2=2(覆盖了终点)。

    • 循环结束。返回 1。正确。

假如循环写成i < nums.size():

  • i会走到 1。此时curDistance是 2。

  • 虽然逻辑上i != curDistance不会触发steps++,但如果之前的curDistance刚好卡在size-1上,走到最后一个元素时再次触发更新,就会多算一步。

  • 核心逻辑:我们在当前点i是为了起跳。如果你已经站在终点了,就不需要再起跳了。

深度复杂度分析

  • 时间复杂度:O(N)

    • 只需要遍历一次数组。

  • 空间复杂度:O(1)

    • 只需要存储距离和步数。

总结:边界的艺术

这道题展示了贪心算法中**“动态规划式”的思维(虽然没用 DP 数组)。 我们把跳跃过程看作是一层一层的波纹**:

  • 第 1 步能到的范围是 A。

  • 第 2 步能到的范围是 B (由 A 中的点跳出来的)。

  • 我们只需要记录波纹的边缘,每碰到一次边缘,步数就 +1。

下一题预告:如果数组中有负数怎么办? 题目要求:K 次取反后最大化数组和。 你可以选择任意一个元素取反(乘 -1),这个操作必须执行 K 次。 贪心策略很有趣:先把绝对值最大的负数变成正数;如果负数都变完了 K 还没用完,那就对着最小的非负数反复取反(消耗 K)。

下期见!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/27 7:21:09

Apache Doris JDBC连接实战:如何让Java应用3步搞定大数据分析?

Apache Doris JDBC连接实战&#xff1a;如何让Java应用3步搞定大数据分析&#xff1f; 【免费下载链接】doris Apache Doris is an easy-to-use, high performance and unified analytics database. 项目地址: https://gitcode.com/gh_mirrors/dori/doris 还在为Java应用…

作者头像 李华
网站建设 2026/9/27 21:44:03

终极密码管理解决方案:MacPass让macOS用户告别密码烦恼

在数字生活中&#xff0c;密码已经成为我们日常身份验证的重要组成部分。MacPass作为一款专为macOS平台设计的原生密码管理器&#xff0c;基于KeePass开源框架构建&#xff0c;为用户提供了安全可靠、操作便捷的密码管理体验。这款应用将密码安全与苹果生态系统完美融合&#x…

作者头像 李华
网站建设 2026/9/27 21:15:40

手把手教你搭建专业级NVR摄像头管理系统

想要构建一个功能强大的RTSP监控系统吗&#xff1f;camera.ui作为一款开源的NVR摄像头管理平台&#xff0c;能够帮助您快速搭建专业的监控解决方案。本文将从零开始&#xff0c;详细指导您完成整个安装和配置过程。 【免费下载链接】camera.ui NVR like user Interface for RTS…

作者头像 李华
网站建设 2026/9/27 8:49:10

ComfyUI-SeedVR2视频放大:3步实现专业级画质提升完整教程

想要将模糊视频瞬间变得清晰锐利吗&#xff1f;ComfyUI-SeedVR2视频放大技术正是您需要的智能解决方案。这款基于先进扩散变换器模型的开源工具&#xff0c;能够智能分析视频内容&#xff0c;在保持原始细节的同时大幅提升分辨率&#xff0c;带来惊艳的画质改善效果。 【免费下…

作者头像 李华