【華為機試】55. 跳躍游戲

文章目錄

  • 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(n2)

三、貪心算法的正確性(直觀解釋 + 循環不變式)

  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(n2)。在 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(n2),本題可用 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; 文章目錄 一、項目介紹二…