遊戲模擬 Jump Game II 青蛙過河 II Leetcode_#45

更新於 發佈於 閱讀時間約 8 分鐘

題目敘述

題目會給我們一個輸入陣列nums,每個元素值代表那個格子點可以跳躍的最大長度

題目保證從最左邊的格子點出發開始跳,一定可以成功抵達終點,請問最少跳躍次數是說少?


題目的原文敘述


測試範例

Example 1:

Input: nums = [2,3,1,1,4]
Output: 2
Explanation: The minimum number of jumps to reach the last index is 2. Jump 1 step from index 0 to 1, then 3 steps to the last index.

0 格跳一格到第 1
1 格跳三格到第 4
總共跳兩次​

Example 2:

Input: nums = [2,3,0,1,4]
Output: 2

0 格跳一格到第 1
1 格跳三格到第 4
總共跳兩次​

約束條件

Constraints:

  • 1 <= nums.length <= 10^4

輸入陣列nums長度介於1~10^4之間。

  • 0 <= nums[i] <= 1000

每個格子點最小可以跳0格,相當於留在原地代表題目可能會給陷阱格子

最大可以跳1000個格子。

  • It's guaranteed that you can reach nums[n - 1].

題目保證一定可以從起點抵達終點。


第一直覺想到就是依照遊戲規則去模擬,盡量往右邊跳,看看跳到終點的最少跳躍次數是多少?

當然是可以的,但是仔細留意一下,nums[i]最大可以有1000,代表每個格子點可能的選擇(也就是分枝)可以有一千條路徑,顯然用直接進行模擬會存在執行速度太慢或者time-out超過時間限制的風險,因為是指數級別的枚舉所有跳躍路徑


這題其實用DFS模擬,或者BFS模擬跳躍,還是勉強可以通過平台的測試。


但是,後面我們會介紹一個更好的演算法,採用貪心策略Greedy strategy的演算法來提升速度

程式法 DFS模擬跳躍

class Solution:
def jump(self, nums: List[int]) -> int:

dp={}

def min_jumps(index):

# Base case, already reach destination
if index>=len(nums)-1:
return 0

# Look-up DP table
if index in dp:
return dp[index]

# DFS to explore all paths, update minimal jump times
step=math.inf
for i in range(index+1,index+nums[index]+1):
step=min(step,1+min_jumps(i))
dp[index]=step
return step
# ---------------------------------------------
return min_jumps(0)

程式碼 BFS模擬跳躍

class Solution:
def jump(self, nums: List[int]) -> int:

destination = len(nums)-1
bfs_q = deque([ (0,0) ])
seen = {0}

while bfs_q:

cur, step = bfs_q.popleft()
if cur >= destination:
return step

for jump in range( nums[cur], 0, -1):

next_pos = (cur + jump)

if next_pos not in seen:
seen.add( next_pos )
bfs_q.append( (next_pos, step+1) )

return -1

演算法 Greedy 策略 盡量去延伸我能抵達的地方,而且到最後非跳不可的時候才跳,盡量減少跳躍次數。


一開始,從起點0出發,在起點做個記號

從起點開始,往右逐一檢查每個格子點,去延伸目前我最遠能跳到哪裡,做個記號

一旦我跳了一步,jump的計數器累加1。

接下來看看目前能跳到哪裡,一旦發現要跨過最後一個記號的時候,才不得已再跳新的一步


當某一步發現能跳到終點時,當下的步數就是最少的跳躍次數。

raw-image



程式碼 Greedy 策略 盡量去延伸我能抵達的地方,而且到最後非跳不可的時候才跳,盡量減少跳躍次數。

class Solution:
def jump(self, nums: List[int]) -> int:

n = len(nums)
destination = n - 1

if destination == 0:
# 邊界條件處理,當只有一個格子時,不用跳就已經在終點。
return 0

max_reach = 0
last_jump_idx = 0
jump_count = 0

for i in range( n ):

max_reach = max(max_reach, i + nums[i] )

# 跨過當下有做記號的最後一格,非不得已才跳一次去延伸跳躍的覆蓋範圍
if i == last_jump_idx:
jump_count += 1
last_jump_idx = max_reach

if max_reach >= destination:
return jump_count

return jump_count

複雜度分析 Greedy 策略 盡量去延伸我能抵達的地方

令n=輸入陣列nums的長度

時間複雜度:

從左邊到右邊逐一檢查每個格子點,盡量去延伸跳躍能覆蓋的範圍爾且盡量節省跳躍是數,總共所需時間為O(n)。


空間複雜度:

用到的都是固定尺寸的臨時變數,總共所需空間為O(1)。


關鍵知識點

演算法 Greedy 策略 盡量去延伸我能抵達的地方,而且到最後非跳不可的時候才跳,盡量減少跳躍次數。


前一題 Jump Game I 有著類似的Greedy策略結構,可以好好互相參照,吸收沉澱,

了解Greedy的涵義: 局部最佳解 推演出 全域的最佳解。


Reference:

[1] Jump Game II_Python O(n) by greedy of coverage

留言
avatar-img
留言分享你的想法!
avatar-img
小松鼠的演算法樂園
95會員
427內容數
由有業界實戰經驗的演算法工程師, 手把手教你建立解題的框架, 一步步寫出高效、清晰易懂的解題答案。 著重在讓讀者啟發思考、理解演算法,熟悉常見的演算法模板。 深入淺出地介紹題目背後所使用的演算法意義,融會貫通演算法與資料結構的應用。 在幾個經典的題目融入一道題目的多種解法,或者同一招解不同的題目,擴展廣度,並加深印象。
2024/09/26
Leetcode 729. My Calendar I 給定一個行事曆的class定義和行程安排的介面interface。 請完成下列function 1.建構子MyCalendar() 初始化MyCalendar物件 2.boolean book(int start, int end) 插入新行程
Thumbnail
2024/09/26
Leetcode 729. My Calendar I 給定一個行事曆的class定義和行程安排的介面interface。 請完成下列function 1.建構子MyCalendar() 初始化MyCalendar物件 2.boolean book(int start, int end) 插入新行程
Thumbnail
2024/09/10
Insert Greatest Common Divisors in Linked List 題目給定一個鏈結串列, 請在兩兩節點之間加入一個新節點,新節點的值為兩者之間的最大公因數。 最後返回新串列的head node作為答案。
Thumbnail
2024/09/10
Insert Greatest Common Divisors in Linked List 題目給定一個鏈結串列, 請在兩兩節點之間加入一個新節點,新節點的值為兩者之間的最大公因數。 最後返回新串列的head node作為答案。
Thumbnail
2024/09/09
2326. Spiral Matrix IV 題目給定一個Linked list和對應的矩陣高度m、寬度n。 請依照順時針的拜訪順序, 從左上角出發,依照次序把Linked List的內容填到矩陣裡。 如果有剩餘不足的空位,就填補-1。 最後將填補好的矩陣返回作為答案。
Thumbnail
2024/09/09
2326. Spiral Matrix IV 題目給定一個Linked list和對應的矩陣高度m、寬度n。 請依照順時針的拜訪順序, 從左上角出發,依照次序把Linked List的內容填到矩陣裡。 如果有剩餘不足的空位,就填補-1。 最後將填補好的矩陣返回作為答案。
Thumbnail
看更多
你可能也想看
Thumbnail
TOMICA第一波推出吉伊卡哇聯名小車車的時候馬上就被搶購一空,一直很扼腕當時沒有趕緊入手。前陣子閒來無事逛蝦皮,突然發現幾家商場都又開始重新上架,價格也都回到正常水準,估計是官方又再補了一批貨,想都沒想就立刻下單! 同文也跟大家分享近期蝦皮購物紀錄、好用推薦、蝦皮分潤計畫的聯盟行銷!
Thumbnail
TOMICA第一波推出吉伊卡哇聯名小車車的時候馬上就被搶購一空,一直很扼腕當時沒有趕緊入手。前陣子閒來無事逛蝦皮,突然發現幾家商場都又開始重新上架,價格也都回到正常水準,估計是官方又再補了一批貨,想都沒想就立刻下單! 同文也跟大家分享近期蝦皮購物紀錄、好用推薦、蝦皮分潤計畫的聯盟行銷!
Thumbnail
每年4月、5月都是最多稅要繳的月份,當然大部份的人都是有機會繳到「綜合所得稅」,只是相當相當多人還不知道,原來繳給政府的稅!可以透過一些有活動的銀行信用卡或電子支付來繳,從繳費中賺一點點小確幸!就是賺個1%~2%大家也是很開心的,因為你們把沒回饋變成有回饋,就是用卡的最高境界 所得稅線上申報
Thumbnail
每年4月、5月都是最多稅要繳的月份,當然大部份的人都是有機會繳到「綜合所得稅」,只是相當相當多人還不知道,原來繳給政府的稅!可以透過一些有活動的銀行信用卡或電子支付來繳,從繳費中賺一點點小確幸!就是賺個1%~2%大家也是很開心的,因為你們把沒回饋變成有回饋,就是用卡的最高境界 所得稅線上申報
Thumbnail
題目敘述 題目會給定一個二元陣列nums(也就是說,陣列元素只有0,1這兩種情況)和指定的k值。 我們最多可以把k個0反轉成1,請問連續唯一的最長子陣列的長度是多少? 題目的原文敘述 測試範例 Example 1: Input: nums = [1,1,1,0,0,0,1,1,1,1,
Thumbnail
題目敘述 題目會給定一個二元陣列nums(也就是說,陣列元素只有0,1這兩種情況)和指定的k值。 我們最多可以把k個0反轉成1,請問連續唯一的最長子陣列的長度是多少? 題目的原文敘述 測試範例 Example 1: Input: nums = [1,1,1,0,0,0,1,1,1,1,
Thumbnail
題目敘述 題目會給兩個陣列nums1和nums2。 題目要求我們從中同步選擇長度為k的子序列,並且最大化子序列的分數, 回傳最高的分數值。 分數的定義: 分數 = (nums1[i0] + nums1[i1] +...+ nums1[ik - 1]) * min(nums2[i0] ,
Thumbnail
題目敘述 題目會給兩個陣列nums1和nums2。 題目要求我們從中同步選擇長度為k的子序列,並且最大化子序列的分數, 回傳最高的分數值。 分數的定義: 分數 = (nums1[i0] + nums1[i1] +...+ nums1[ik - 1]) * min(nums2[i0] ,
Thumbnail
題目敘述 題目會給我們一個輸入陣列arr,起始點固定在索引為0的位置, 終點固定在索引為n-1的位置。 假設當下所在的索引位置為i,那麼每次移動的時候,可以跳到i-1,i+1,或者其他和我有相同元素值的位置arr[j], where arr[j] = arr[i]。 例如: 假設當下在i=3
Thumbnail
題目敘述 題目會給我們一個輸入陣列arr,起始點固定在索引為0的位置, 終點固定在索引為n-1的位置。 假設當下所在的索引位置為i,那麼每次移動的時候,可以跳到i-1,i+1,或者其他和我有相同元素值的位置arr[j], where arr[j] = arr[i]。 例如: 假設當下在i=3
Thumbnail
題目敘述 題目會給我們一個輸入陣列nums,每個元素值代表那個格子點可以左右位移的固定長度。 例如,假設 nums[i] = 3,那麼下一步可以移動到nums[i-3] 或 nums[i+3]這兩個格子點。 題目​會給定一個起始點start索引位置,請問我們能不能走到內部數值為0的格子點?
Thumbnail
題目敘述 題目會給我們一個輸入陣列nums,每個元素值代表那個格子點可以左右位移的固定長度。 例如,假設 nums[i] = 3,那麼下一步可以移動到nums[i-3] 或 nums[i+3]這兩個格子點。 題目​會給定一個起始點start索引位置,請問我們能不能走到內部數值為0的格子點?
Thumbnail
題目敘述 題目會給我們一個輸入陣列nums,每個元素值代表那個格子點可以跳躍的最大長度。 題目保證始從最左邊的格子點出發開始跳,一定可以成功抵達終點,請問最少跳躍次數是說少? 題目的原文敘述 測試範例 Example 1: Input: nums = [2,3,1,1,4] Outp
Thumbnail
題目敘述 題目會給我們一個輸入陣列nums,每個元素值代表那個格子點可以跳躍的最大長度。 題目保證始從最左邊的格子點出發開始跳,一定可以成功抵達終點,請問最少跳躍次數是說少? 題目的原文敘述 測試範例 Example 1: Input: nums = [2,3,1,1,4] Outp
Thumbnail
題目敘述 題目會給我們一個輸入陣列nums,每個元素值代表那個格子點可以跳躍的最大長度。 一開始從最左邊的格子點出發開始跳,請問可以成功抵達終點,也就是最右邊的格子點嗎? 如果可以,返回 True。 如果不行,返回False。 題目的原文敘述 測試範例 Example 1: In
Thumbnail
題目敘述 題目會給我們一個輸入陣列nums,每個元素值代表那個格子點可以跳躍的最大長度。 一開始從最左邊的格子點出發開始跳,請問可以成功抵達終點,也就是最右邊的格子點嗎? 如果可以,返回 True。 如果不行,返回False。 題目的原文敘述 測試範例 Example 1: In
Thumbnail
題目敘述 題目會給定一個指定高度和寬的方格版,還有一顆小球的起始位置,和最大移動步數。 小球每一步可以選擇向上、下、左、右移動一格,請問小球能走到方格版界外的路徑方法數總共有幾種? 方法數可能很大,題目要求,最後回傳答案時,先對10^9+7做除法取餘數再回傳。 題目的原文敘述 約束條件
Thumbnail
題目敘述 題目會給定一個指定高度和寬的方格版,還有一顆小球的起始位置,和最大移動步數。 小球每一步可以選擇向上、下、左、右移動一格,請問小球能走到方格版界外的路徑方法數總共有幾種? 方法數可能很大,題目要求,最後回傳答案時,先對10^9+7做除法取餘數再回傳。 題目的原文敘述 約束條件
Thumbnail
題目敘述 題目會給我們一個二維陣列matrix,分別代表每個格子的成本,請問我們從最頂端到底部的下墜路徑的最小成本總和是多少? 每次下墜到下一排的時候,可以有三種選擇: 1.往左下角移動。 2.往正下方移動。 3.往右下角移動。 題目的原文敘述 測試範例 Example 1:
Thumbnail
題目敘述 題目會給我們一個二維陣列matrix,分別代表每個格子的成本,請問我們從最頂端到底部的下墜路徑的最小成本總和是多少? 每次下墜到下一排的時候,可以有三種選擇: 1.往左下角移動。 2.往正下方移動。 3.往右下角移動。 題目的原文敘述 測試範例 Example 1:
Thumbnail
題目會給定我們一個陣列,要求我們重新安排順序,把等於零的數字搬到後面。 同時必須保持原本數字的前後相對次序。
Thumbnail
題目會給定我們一個陣列,要求我們重新安排順序,把等於零的數字搬到後面。 同時必須保持原本數字的前後相對次序。
Thumbnail
爬到頂樓的最小成本, 這題算是前面那題Climbing stairs的變形題,有點小變化, 但是稍微想一下還是能推導出來,算是很好的一維動態規劃1D DP練習題。
Thumbnail
爬到頂樓的最小成本, 這題算是前面那題Climbing stairs的變形題,有點小變化, 但是稍微想一下還是能推導出來,算是很好的一維動態規劃1D DP練習題。
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News