文章目录

  • 55. 跳跃游戏
    • 题目描述
    • 示例 1:
    • 示例 2:
    • 提示:
    • 解题思路
      • 一、问题本质与建模
      • 二、方法总览与选择
      • 三、贪心算法的正确性(直观解释 + 循环不变式)
      • 四、反向贪心:等价但有启发的视角
      • 五、与动态规划的对比与误区澄清
      • 六、过程可视化(示例一)
      • 七、边界与坑点汇总
      • 八、复杂度与工程实践
      • 九、相关变体与延伸
      • 十、常见面试追问(简答)
    • 代码实现
    • 测试用例设计
    • 小结
    • 完整题解代码

55. 跳跃游戏

题目描述

给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。

判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。

示例 1:

输入:nums = [2,3,1,1,4]
输出:true
解释:可以先跳 1 步,从下标 0 到达下标 1, 然后再从下标 1 跳 3 步到达最后一个下标。

示例 2:

输入:nums = [3,2,1,0,4]
输出:false
解释:无论怎样,总会到达下标为 3 的位置。但该下标的最大跳跃长度是 0 , 所以永远不可能到达最后一个下标。

提示:

  • 1 <= nums.length <= 10^4
  • 0 <= nums[i] <= 10^5

解题思路

一、问题本质与建模

将每个位置 i 看作一“跳板”,可直接把你送到区间 [i+1, i+nums[i]] 中的任意位置(含边界)。问题转化为:从起点 0 出发,是否存在一条“跳板链”使得你可以覆盖到 n-1。这天然是一个“可达性”问题。

直觉上,只要我们始终维护“从已访问过的所有位置出发,能到达的最远下标”,就能判断是否触达终点。这便是贪心策略的核心:每前进一步,就尽力扩展我们能到达的“最远边界”。

二、方法总览与选择

graph TDA[跳跃游戏 方法选择] --> B[贪心: 维护最远可达]A --> C[反向贪心: 收缩 lastGood]A --> D[DP: 从后往前可达性]B --> E[O(n)时间 O(1)空间 最优]C --> F[O(n)时间 O(1)空间 等价视角]D --> G[O(n^2)时间 O(n)空间 仅教学]
  • 贪心(正向):迭代 i 并维护 farthest = max(farthest, i + nums[i])
  • 反向贪心:维护“必须到达”的最右位置 lastGood,若 i + nums[i] >= lastGoodlastGood = i
  • DP:dp[i] = OR(dp[j]) for j in (i, i+nums[i]],直观但最坏 O(n²)

三、贪心算法的正确性(直观解释 + 循环不变式)

  1. 直观解释(区间扩展模型)
  • 在第 i 步之前,我们已经保证所有 <= i 的点都“被访问过”(即可达)。
  • 访问 i 时,i 能贡献的新可达区间为 [i+1, i+nums[i]],因此最远可达位置应被更新为 max(farthest, i+nums[i])
  • 一旦 farthest >= n-1,说明终点被区间覆盖,立即返回 true
  1. 循环不变式(关键性质)
  • 不变式:在进入第 i 次循环时,[0, i] 中所有点均可达,且 farthest 是这些点能共同“覆盖”的最远下标。
  • 维持:若 i <= farthest,则 i 可达;更新 farthest = max(farthest, i+nums[i]) 后,不变式对 i+1 继续成立。
  • 违例检测:若出现 i > farthest,说明 i 不可达,不变式被打破,也就不可能再扩展任何区间,直接返回 false
  1. 最优性与“局部最优 -> 全局最优”
  • 我们在每一步都“尽可能把可达区间向右扩展”,这是天然的局部最优。
  • 对于可达性问题,是否能到达终点仅依赖“区间最右端”。局部最优的持续累积,直接决定全局可达性,因此贪心是最优解。

四、反向贪心:等价但有启发的视角

从右向左设定 lastGood = n-1,若 i + nums[i] >= lastGood,则从 i 出发可以到达 lastGood,因此把“必须到达”的点收缩为更靠左的 i。最后若 lastGood == 0,说明起点可达。这与正向贪心等价,但从“目标回溯”的角度更易让人信服。

五、与动态规划的对比与误区澄清

  • DP 的状态非常自然,但转移需要枚举可跳范围,导致最坏 O(n²)。在 n=10^4 的上限下会超时或性能很差。
  • 有同学会尝试 BFS/最短路,但本题不问“最少步数”,只问“能否到达”,贪心一次扫描即可。
  • 另一些做法会“实际模拟每一次跳跃”,容易漏掉“从更靠后的位置起跳能跳得更远”的可能性;贪心用区间端点统一管理,避免了这种陷阱。

六、过程可视化(示例一)

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

inums[i]farthest(更新前)能覆盖的新右端farthest(更新后)结论
0200+2=22可达
1321+3=44可达,已>=4 返回true

i=1 时即可确定答案,早停是工程实现的重要优化点。

七、边界与坑点汇总

  • n=1(单元素):必定 true
  • 出现长串 0:只要 0 左边的某个位置能一次“跨越”它们即可;否则在 i > farthest 时返回 false
  • 大数值:无需担心溢出,i + nums[i]int 范围内,且只与数组长度比较
  • 早停:一旦 farthest >= n-1,即可直接返回 true

八、复杂度与工程实践

  • 时间复杂度:O(n)。每个位置只访问一次,且仅进行 O(1) 更新
  • 空间复杂度:O(1)。只维护少量标量变量
  • 工程建议:
    • 使用早停减少不必要的循环
    • 保持变量语义清晰(如 farthestlastGood),利于代码可读性与维护

九、相关变体与延伸

  • Jump Game II(最少跳跃次数):层次 BFS/贪心分层更新可解,注意与本题“可达性判断”的区别
  • Jump Game III(含负数与图可达性):需要访问标记避免重复,更多是图搜索问题
  • 带代价/概率的跳跃:演化为最短路/期望优化等问题

十、常见面试追问(简答)

  • 为什么贪心正确?因为“能否到达”只与区间最右端相关,持续取最大右端的策略能完整保留一切潜在可达路径的信息(循环不变式保证)。
  • 为什么不用 DP?DP 的最坏时间 O(n²),本题可用 O(n) 解法,工程上应优先选贪心。
  • 有反例吗?对于“只问可达性”的版本,贪心没有反例;但若问“最少步数”,需要不同策略(分层贪心/ BFS)。

代码实现

完整可运行代码见 main.go,包含三种方法(贪心、反向贪心、DP)和测试/小型性能对比。

示例片段(贪心):

func canJumpGreedy(nums []int) bool {farthest := 0for i := 0; i < len(nums); i++ {if i > farthest {return false}if i+nums[i] > farthest {farthest = i + nums[i]}if farthest >= len(nums)-1 {return true}}return true
}

测试用例设计

测试
可达样例
不可达样例
边界情况
2,3,1,1,4
3,2,1,0,4
单元素/被0阻断/大步跳过

建议覆盖:

  • 基础示例(题目给定)
  • 被 0 阻断导致不可达
  • 单元素 0、全 1、首位一次大跳

小结

  • 本质是“区间可达性”问题,维护“最远可达端点”即可一次扫描判定
  • 贪心与反向贪心等价,前者便于实现,后者便于论证
  • DP 直观但性能差,保留为思路对比和单元测试的参照

完整题解代码

package mainimport ("fmt""strings""time"
)// 解法一:贪心(最优解,时间O(n),空间O(1))
// 维护最远可达下标 farthest,可以在遍历过程中动态扩展可达范围。
// 若某一时刻 i > farthest,说明当前位置不可达,直接返回 false。
// 最终只要 farthest >= n-1 即可到达终点。
func canJumpGreedy(nums []int) bool {farthest := 0for i := 0; i < len(nums); i++ {if i > farthest {return false}if i+nums[i] > farthest {farthest = i + nums[i]}if farthest >= len(nums)-1 {return true}}return true
}// 解法二:动态规划(从后往前,时间O(n^2),空间O(n))
// dp[i] 表示从 i 出发是否能到达终点。枚举 i 能跳到的每个 j,看是否有 dp[j] 为真。
// 仅用于教学对比,实际大数据会超时;可加剪枝或二分优化思路,但贪心更优雅。
func canJumpDP(nums []int) bool {n := len(nums)dp := make([]bool, n)dp[n-1] = truefor i := n - 2; i >= 0; i-- {maxJ := min(i+nums[i], n-1)for j := i + 1; j <= maxJ; j++ {if dp[j] {dp[i] = truebreak}}}return dp[0]
}// 解法三:反向贪心(从右往左收缩目标,时间O(n),空间O(1))
// 维护一个 lastGood 作为“必须到达”的最右位置;如果 i + nums[i] >= lastGood,
// 则把 lastGood 更新为 i。最终判断 lastGood == 0。
func canJumpReverseGreedy(nums []int) bool {lastGood := len(nums) - 1for i := len(nums) - 2; i >= 0; i-- {if i+nums[i] >= lastGood {lastGood = i}}return lastGood == 0
}// 测试与简单性能对比
func runTests() {type testCase struct {nums     []intexpected booldesc     string}tests := []testCase{{[]int{2, 3, 1, 1, 4}, true, "示例1 可达"},{[]int{3, 2, 1, 0, 4}, false, "示例2 不可达"},{[]int{0}, true, "单元素 0"},{[]int{1, 0, 1, 0}, false, "被 0 阻断"},{[]int{2, 0, 0}, true, "边界跳过"},{[]int{1, 1, 1, 1}, true, "全 1"},{[]int{4, 0, 0, 0, 0}, true, "首位大跳"},}fmt.Println("=== 55. 跳跃游戏 - 测试 ===")for i, tc := range tests {g := canJumpGreedy(tc.nums)r := canJumpReverseGreedy(tc.nums)d := canJumpDP(tc.nums)ok := (g == tc.expected) && (r == tc.expected) && (d == tc.expected)status := "✅"if !ok {status = "❌"}fmt.Printf("用例 %d: %s\n", i+1, tc.desc)fmt.Printf("输入: %v\n期望: %v\n贪心: %v, 反向贪心: %v, DP: %v\n", tc.nums, tc.expected, g, r, d)fmt.Printf("结果: %s\n", status)fmt.Println(strings.Repeat("-", 40))}
}func benchmark() {fmt.Println("\n=== 简单性能对比(粗略) ===")// 构造较大用例:长度 100000,前面给出足够跳力n := 100000nums := make([]int, n)for i := 0; i < n-1; i++ {nums[i] = 2}nums[n-1] = 0start := time.Now()_ = canJumpGreedy(nums)d1 := time.Since(start)start = time.Now()_ = canJumpReverseGreedy(nums)d2 := time.Since(start)// 警告:O(n^2) DP 在大输入上会非常慢,这里仅做一次小规模对比small := []int{2, 3, 1, 1, 4, 0, 0, 3, 1, 2, 0}start = time.Now()_ = canJumpDP(small)d3 := time.Since(start)fmt.Printf("贪心: %v\n", d1)fmt.Printf("反向贪心: %v\n", d2)fmt.Printf("DP(小规模): %v\n", d3)
}func min(a, b int) int {if a < b {return a}return b
}func main() {fmt.Println("55. 跳跃游戏")fmt.Println(strings.Repeat("=", 40))runTests()benchmark()
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/diannao/95083.shtml
繁体地址,请注明出处:http://hk.pswp.cn/diannao/95083.shtml
英文地址,请注明出处:http://en.pswp.cn/diannao/95083.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

RabbitMQ面试精讲 Day 18:内存与磁盘优化配置

【RabbitMQ面试精讲 Day 18】内存与磁盘优化配置 开篇&#xff1a;内存与磁盘优化的重要性 欢迎来到"RabbitMQ面试精讲"系列的第18天&#xff01;今天我们将深入探讨RabbitMQ的内存与磁盘优化配置&#xff0c;这是面试中经常被问及的高频主题&#xff0c;也是生产环…

【C++】string 的特性和使用

Ciallo&#xff5e; (∠・ω< )⌒★ string&#xff08;1&#xff09;1. 构造函数1.1 string();1.2 string(const char* s);1.3 string(const string& str);1.4 string(size_t n, char c);1.5 string(const string& str, size_t pos, size_t len npos);1.6 string(…

创始人IP的精神修炼:于成长中积蓄力量

IP 经济席卷之下&#xff0c;众多企业家常被 “是否入局 IP”“能否做好 IP” 的焦虑裹挟。这种潜藏的精神内耗&#xff0c;对企业根基的侵蚀往往胜过业绩的起伏。著名文化学者于丹在全球创始人 IP 领袖高峰论坛上的洞见&#xff0c;为创始人 IP 的精神成长照亮了前路&#xff…

gbase8s数据库中对象元数据查询

最近整理了gbase8s数据库中常见的元数据的查询&#xff0c;包括表、视图、序列、包、类型、触发器、plsql等等&#xff0c;仅供参考。set environment sqlmode oracle; drop package DBMS_METADATA; create or replace package DBMS_METADATA is function GET_DDL(objtype varc…

常用hook钩子函数

爬虫Hook技术常用字段和勾子函数 目录 Hook技术概述网络请求相关Hook浏览器环境HookJavaScript引擎Hook加密算法Hook反爬虫检测Hook实际应用示例Hook工具和框架 Hook技术概述 Hook&#xff08;钩子&#xff09;技术是一种在程序运行时拦截和修改函数调用的技术。在爬虫中&a…

【解决方法】华为电脑的亮度调节失灵

华为电脑的亮度调节失灵 参考文章&#xff1a; 华为电脑屏幕亮度怎么调不了&#xff1f;华为电脑调节亮度没反应解决教程 亲测&#xff0c;在控制面板中卸载HWOSD&#xff0c;再重装有用。

【软考中级网络工程师】知识点之 DCC 深度剖析

目录一、DCC 是什么1.1 定义阐述1.2 作用讲解二、DCC 工作原理2.1 拨号触发机制2.1.1 感兴趣流量定义2.1.2 触发拨号过程2.2 链路建立流程2.2.1 物理链路连接2.2.2 数据链路层协议协商三、DCC 配置要点3.1 基础配置步骤3.1.1 接口配置3.1.2 拨号映射配置3.2 高级配置参数3.2.1 …

W5500之Socket寄存器区介绍

W5500之Socket寄存器区介绍1)、Socket n模式寄存器(Socket n Mode Register&#xff0c;简写Sn_MR)偏移地址为0x0000&#xff0c;可读写&#xff0c;复位值为0x00&#xff1b;Bit7Bit6Bit5Bit4Bit3Bit2Bit1Bit0MULTI/MFENBCASTBND/MC/MMBUCASTB/MIP6BP3P2P1P0MULTI/MFEN占用“S…

酉矩阵(Unitary Matrix)和随机矩阵

先讨论酉矩阵&#xff08;Unitary Matrix&#xff09;的性质。1. 酉矩阵定义酉矩阵&#xff08;Unitary Matrix&#xff09;是复数域上的方阵&#xff0c;满足以下条件&#xff1a;其中&#xff1a;是 的共轭转置&#xff08;即 Hermitian 转置&#xff0c; &#xff09;。是单…

「iOS」————单例与代理

iOS学习单例代理代理模式的原理代理的循环引用设计模式单例 优点&#xff1a; 全局访问&#xff1a;单例模式确保一个类只有一个实例&#xff0c;并提供全局访问点&#xff0c;方便在整个应用中共享数据或功能。节省资源&#xff1a;由于只创建一个实例&#xff0c;可以减少内…

Microsoft Dynamics AX 性能优化解决方案

一、方案背景Microsoft Dynamics AX 是功能强大的企业ERP系统&#xff0c;虽然Microsoft 已推出基于云的现代化 ERP 平台 Dynamics 365 Finance and Operations&#xff0c;提供了更高的性能和持续更新&#xff0c;用来替代Dynamics AX。在考虑升级到Dynamics 365之前&#xff…

ARM保留的标准中断处理程序入口和外设中断处理程序入口介绍

在ARM架构中&#xff0c;中断处理是一个关键机制&#xff0c;它允许CPU在执行主程序时能够响应外部或内部的事件。对于ARM MCU&#xff08;微控制器单元&#xff09;而言&#xff0c;中断处理程序入口通常分为两类&#xff1a;ARM保留的标准中断处理程序入口和外设中断处理程序…

防火墙环境下的全网服务器数据自动化备份平台搭建:基于 rsync 的完整实施指南

一、项目总览 1.内容介绍 本文以 3 台 CentOS 7.9 服务器&#xff08;Web 服务器、NFS 服务器、备份服务器&#xff09;为载体&#xff0c;详解如何在全防火墙开启的前提下&#xff0c;搭建一套自动化数据备份平台&#xff1a;每日自动打包 Web 站点、NFS 共享数据及系统关键…

Spring之【Import】

目录 Import注解 源码分析 使用示例 ImportSelector 源码分析 使用示例 DeferredImportSelector 源码分析 使用示例 ImportBeanDefinitionRegistrar 源码分析 使用示例 Import注解 源码分析 处理组件类上的Import注解 将Import引入类对应的BeanDefinition对象添加…

RN项目环境搭建和使用-Mac版本(模拟器启动不起来的排查)

ReactNative&#xff1a; https://github.com/facebook/react-native https://reactnative.cn/docs/getting-started &#xff08;可以先通读一下这个&#xff09; 环境搭建 &#xff08;mac版&#xff09;https://juejin.cn/post/7404860612758765605 搭建之前确认版本&#x…

悬赏任务系统网站兼职赚钱小程序搭建地推抖音视频任务拉新源码功能详解二开

功能详解&#xff08;一&#xff09;登录与注册1、登录&#xff1a;打开系统用户端&#xff0c;输入已注册的手机号&#xff0c;若为首次登录或忘记密码&#xff0c;可通过 “找回密码” 功能&#xff0c;按提示验证身份后重置密码登录。 2、注册&#xff1a;点击 “注册” 按钮…

scikit-learn/sklearn学习|线性回归解读

【1】引言 前序学习进程中&#xff0c;对SVM相关的数学原理进行了探索和推导&#xff0c;相关文章链接包括且不限于&#xff1a; python学智能算法&#xff08;二十六&#xff09;|SVM-拉格朗日函数构造-CSDN博客 python学智能算法&#xff08;二十八&#xff09;|SVM-拉格朗…

音视频学习(五十一):AAC编码器

什么是AAC编码器&#xff1f; 高级音频编码&#xff08;Advanced Audio Coding&#xff0c;简称AAC&#xff09; 是一种有损音频压缩技术&#xff0c;旨在作为MP3的下一代标准而开发。它的主要目标是在比MP3更低的比特率下提供更好的音质&#xff0c;同时具备更强的灵活性和功能…

10-netty基础-手写rpc-定义协议头-02

netty系列文章&#xff1a; 01-netty基础-socket02-netty基础-java四种IO模型03-netty基础-多路复用select、poll、epoll04-netty基础-Reactor三种模型05-netty基础-ByteBuf数据结构06-netty基础-编码解码07-netty基础-自定义编解码器08-netty基础-自定义序列化和反序列化09-n…

计算机毕设缺乏创新点?基于大数据的快手平台用户活跃度分析系统给你思路【程序开发+项目定制】

精彩专栏推荐订阅&#xff1a;在 下方专栏&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f496;&#x1f525;作者主页&#xff1a;计算机毕设木哥&#x1f525; &#x1f496; 文章目录 一、项目介绍二…