文章目錄
1306. 跳躍遊戲 III
難度:中等
這裏有一個非負整數數組 arr,你最開始位於該數組的起始下標 start 處。當你位於下標 i 處時,你可以跳到 i + arr[i] 或者 i - arr[i]。
請你判斷自己是否能夠跳到對應元素值爲 0 的 任意 下標處。
注意,不管是什麼情況下,你都無法跳到數組之外。
示例 1:
輸入:arr = [4,2,3,0,3,1,2], start = 5
輸出:true
解釋:
到達值爲 0 的下標 3 有以下可能方案:
下標 5 -> 下標 4 -> 下標 1 -> 下標 3
下標 5 -> 下標 6 -> 下標 4 -> 下標 1 -> 下標 3
示例 2:
輸入:arr = [4,2,3,0,3,1,2], start = 0
輸出:true
解釋:
到達值爲 0 的下標 3 有以下可能方案:
下標 0 -> 下標 4 -> 下標 1 -> 下標 3
示例 3:
輸入:arr = [3,0,2,1,2], start = 2
輸出:false
解釋:無法到達值爲 0 的下標 1 處。
提示:
- 1 <= arr.length <= 5 * 10^4
- 0 <= arr[i] < arr.length
- 0 <= start < arr.length
解決方案 :
深度遍歷:關鍵在於標記,意思是當向樹深度遍歷時,要記得對遍歷的位置進行標記防止反覆遍歷,當遍歷不下去時還需要記得刪除該標記,防止其他數分支訪問不到該節點,若無節點可訪問時,則返回false;若訪問到的節點符合條件時,則返回True。
class Solution:
def dfs(self, arr, start, mark):
print(start, arr[start])
if arr[start] == 0:
return True
mark[start] += 1
if 0 <= start - arr[start] < len(arr) and mark[start - arr[start]] == 0:
if self.dfs(arr, start - arr[start], mark):
return True
if 0 <= start + arr[start] < len(arr) and mark[start + arr[start]] == 0:
if self.dfs(arr, start + arr[start], mark):
return True
mark[start] -= 1
return False
def canReach(self, arr: List[int], start: int) -> bool:
return self.dfs(arr, start, [0 for _ in range(len(arr))])
廣度遍歷:與深度遍歷不同的是,除了要標記訪問的節點外,廣度遍歷重點是首先要設定一個數組,作爲廣度遍歷的源頭,且每次遍歷這個數組以廣度進行遍歷並更新這個數組,如果這個數組沒值時,則返回False。
以下是網上某大神寫的廣度遍歷:
class Solution:
def canReach(self, arr: List[int], start: int) -> bool:
q, v, n = [start], {start}, len(arr)
while q:
p = []
for i in q:
if not arr[i]:
return True
for j in i - arr[i], i + arr[i]:
if 0 <= j < n and j not in v:
p.append(j)
v.add(j)
q = p
return False
順帶附上該大神的深度遍歷,很便捷。
class Solution:
def canReach(self, arr: List[int], start: int) -> bool:
n, v = len(arr), set()
def f(i):
if not arr[i]:
return True
elif i not in v:
v.add(i)
return 0 <= i - arr[i] < n and f(i - arr[i]) or 0 <= i + arr[i] < n and f(i + arr[i])
return f(start)