文章目录
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)