一題多解 遊戲模擬 Jump Game III 青蛙過河 III Leetcode_#1306

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

題目敘述

題目會給我們一個輸入陣列nums,每個元素值代表那個格子點可以左右位移的固定長度

例如,假設 nums[i] = 3,那麼下一步可以移動到nums[i-3] 或 nums[i+3]這兩個格子點。


題目​給定一個起始點start索引位置,請問我們能不能走到內部數值為0的格子點?

可以的話返回True。

無解的話返回False。


題目的原文敘述


測試範例

Example 1:

Input: arr = [4,2,3,0,3,1,2], start = 5
Output: true
Explanation:
All possible ways to reach at index 3 with value 0 are:
index 5 -> index 4 -> index 1 -> index 3
index 5 -> index 6 -> index 4 -> index 1 -> index 3

Example 2:

Input: arr = [4,2,3,0,3,1,2], start = 0
Output: true
Explanation:
One possible way to reach at index 3 with value 0 is:
index 0 -> index 4 -> index 1 -> index 3

Example 3:

Input: arr = [3,0,2,1,2], start = 2
Output: false
Explanation: There is no way to reach at index 1 with value 0.

約束條件

Constraints:

  • 1 <= arr.length <= 5 * 10^4

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

  • 0 <= arr[i] < arr.length

每個陣列元素值都界於0~陣列長度之間。

  • 0 <= start < arr.length

起始點一定是合法位置,不會在界外。


演算法

根據題意描述,這是一條判定路徑存在與否的問題。

抽象地想,我們可以把

每個陣列格子點視為一個節點

陣列的值就代表指向另外兩個節點 i - nums[i] 和 i + nums[i]的指向邊。


到這一步,我們就把路徑存在與否的問題,轉換成圖論上的路徑搜索問題。

現在題目被我們映射到一個等價的問題,從nums[start]節點開始走,是否存在一條路徑走到終點nums[end], 而且 nums[end]值為0。


這邊以範例一的圖解幫助大家思考。

Example 1:

Input: arr = [4,2,3,0,3,1,2], start = 5

Output: true

Explanation:

All possible ways to reach at index 3 with value 0 are:

index 5 -> index 4 -> index 1 -> index 3

index 5 -> index 6 -> index 4 -> index 1 -> index 3

每個陣列格子點視為一個節點

陣列的值就代表指向另外兩個節點 i - nums[i] 和 i + nums[i]的指向邊。

畫成圖,就變成下方這個樣子。


起點是5,問我們能不能從5號節點走向終點,而且終點的節點值value = 0

raw-image

答案是可以,我們可以用DFS和BFS去做路徑搜索,最後有兩條路徑可以走到終點,終點是左下角的3號節點,節點值value=0。


綠色部分就是從起點start=5走向終點(節點值value=0)的路徑

ID 5 -> ID 4 -> ID 1 -> ID 3,節點值value = 0

raw-image


ID 5 -> ID 6 -> ID 4 -> ID 1 -> ID 3,節點值value = 0

raw-image

程式碼 DFS

class Solution:
def canReach(self, arr: List[int], start: int) -> bool:

# Base case aka stop condition

# Invalid index checking, or repeated traversal
if ( ( start < 0) or (start >= len(arr) ) or ( arr[ start ] == -1) ):
return False;


# Reach destination
if arr[ start ] == 0 :
return True;

# General cases:
offset = arr[ start ]

# mark as visited
arr[start] = -1

# search in DFS
return self.canReach(arr, start + offset ) or self.canReach( arr, start - offset )

複雜度分析 DFS 尋找路徑

令n=輸入陣列nums的長度 = 圖中的節點總數

時間複雜度:

從start拜訪整張圖,每個節點至多訪問一次,每個節點最多兩條向外的指向邊。

最後一定有結果,若有路徑回傳True,若無解則回傳False。


拜訪整張圖所需時間為O(n)。


空間複雜度:

從起點開始DFS遞迴搜索,每一層拜訪一個節點,最大深度為O(n)。


程式碼 BFS

class Solution:
def canReach(self, arr: List[int], start: int) -> bool:

if arr[start] == 0:
return True

n = len(arr)

# mark as visited
seen = {start}
bfs_q = deque([start])

while bfs_q:
u = bfs_q.popleft()
for next_node in [u + arr[u], u - arr[u]]:
if 0 <= next_node < n and next_node not in seen:
if arr[next_node] == 0:
return True

bfs_q.append(next_node)

# # mark as visited
seen.add(next_node)

return False


複雜度分析 BFS 尋找路徑

令n=輸入陣列nums的長度 = 圖中的節點總數

時間複雜度:

從start拜訪整張圖,每個節點至多訪問一次,每個節點最多兩條向外的指向邊。

最後一定有結果,若有路徑回傳True,若無解則回傳False。


拜訪整張圖所需時間為O(n)。


空間複雜度:

從起點開始BFS逐層搜索,先進先出拜訪一個節點,queue最大長度為O(n)。


關鍵知識點

把原本的題目映射到圖論上的找路徑問題

由從找路徑聯想到其實就是拜訪整張圖

拜訪整張圖想到圖論裡最泛用的DFS深度優先搜索 BFS廣度優先搜索


Reference:

[1] Jump Game III_Python O(n) by DFS

留言
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
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
「欸!這是在哪裡買的?求連結 🥺」 誰叫你太有品味,一發就讓大家跟著剁手手? 讓你回購再回購的生活好物,是時候該介紹出場了吧! 「開箱你的美好生活」現正召喚各路好物的開箱使者 🤩
Thumbnail
題目敘述 Single Number III 給定一個輸入陣列,已知有兩個烙單的數字,其他剩餘的數字都恰巧出現兩次。 請找出這兩個烙單的數字。 題目額外提出限制,請使用O(n)線性時間、O(1)常數空間複雜度的演算法。 測試範例 Example 1: Input: nums = [1,
Thumbnail
題目敘述 Single Number III 給定一個輸入陣列,已知有兩個烙單的數字,其他剩餘的數字都恰巧出現兩次。 請找出這兩個烙單的數字。 題目額外提出限制,請使用O(n)線性時間、O(1)常數空間複雜度的演算法。 測試範例 Example 1: Input: nums = [1,
Thumbnail
題目敘述 輸入給定一個鏈結串列的head node。 要求我們進行化簡,只要某個節點的右手邊存在比較大的節點,就刪除掉。 例如 5->2->13->3 5的右手邊有13,所以5刪除掉。 2的右手邊有13,所以2刪除掉。 13的右手邊沒有更大的節點,所以13留著。 3的右手邊沒有更大
Thumbnail
題目敘述 輸入給定一個鏈結串列的head node。 要求我們進行化簡,只要某個節點的右手邊存在比較大的節點,就刪除掉。 例如 5->2->13->3 5的右手邊有13,所以5刪除掉。 2的右手邊有13,所以2刪除掉。 13的右手邊沒有更大的節點,所以13留著。 3的右手邊沒有更大
Thumbnail
題目敘述 題目會給定一棵二元樹的根結點, 要求我們計算滿足局部路徑節點和=targetSum的數目有多少? 註: 局部路徑節點和 =由節點a往下走到某個節點b,這個區間內的節點值總和 題目的原文敘述 測試範例 Example 1: Input: root = [10,5,-3,3
Thumbnail
題目敘述 題目會給定一棵二元樹的根結點, 要求我們計算滿足局部路徑節點和=targetSum的數目有多少? 註: 局部路徑節點和 =由節點a往下走到某個節點b,這個區間內的節點值總和 題目的原文敘述 測試範例 Example 1: Input: root = [10,5,-3,3
Thumbnail
題目敘述 題目會給定我們一個整數陣列nums,要求我們把裡面的0做元素交換,把0都搬到陣列的右邊。題目要求必須in-place在原本的陣列裡面做操作,不可以額外建立新的陣列。 題目的原文敘述 測試範例 Example 1: Input: nums = [0,1,0,3,12] Outpu
Thumbnail
題目敘述 題目會給定我們一個整數陣列nums,要求我們把裡面的0做元素交換,把0都搬到陣列的右邊。題目要求必須in-place在原本的陣列裡面做操作,不可以額外建立新的陣列。 題目的原文敘述 測試範例 Example 1: Input: nums = [0,1,0,3,12] Outpu
Thumbnail
題目敘述 題目會給我們一個輸入陣列nums,要求我們判斷輸入陣列nums內部是否存在長度為三的遞增子序列? 題目的原文敘述 測試範例 Example 1: Input: nums = [1,2,3,4,5] Output: true Explanation: Any triplet wh
Thumbnail
題目敘述 題目會給我們一個輸入陣列nums,要求我們判斷輸入陣列nums內部是否存在長度為三的遞增子序列? 題目的原文敘述 測試範例 Example 1: Input: nums = [1,2,3,4,5] Output: true Explanation: Any triplet wh
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的格子點?
追蹤感興趣的內容從 Google News 追蹤更多 vocus 的最新精選內容追蹤 Google News