給你一棵二叉樹的根節點 root
,二叉樹中節點的值 互不相同 。另給你一個整數 start
。在第 0
分鐘,感染 將會從值爲 start
的節點開始爆發。
每分鐘,如果節點滿足以下全部條件,就會被感染:
- 節點此前還沒有感染。
- 節點與一個已感染節點相鄰。
返回感染整棵樹需要的分鐘數。
示例 1:
輸入:root = [1,5,3,null,4,10,6,9,2], start = 3
輸出:4
解釋:節點按以下過程被感染:
- 第 0 分鐘:節點 3
- 第 1 分鐘:節點 1、10、6
- 第 2 分鐘:節點5
- 第 3 分鐘:節點 4
- 第 4 分鐘:節點 9 和 2
感染整棵樹需要 4 分鐘,所以返回 4 。
示例 2:
輸入:root = [1], start = 1
輸出:0
解釋:第 0 分鐘,樹中唯一一個節點處於感染狀態,返回 0 。
提示:
- 樹中節點的數目在範圍
[1, 105]
內 1 <= Node.val <= 105
- 每個節點的值 互不相同
- 樹中必定存在值爲
start
的節點
這道題本質上就是求start
節點到樹中其他節點的最遠距離,本來的想法是最遠節點要麼是start
節點繼續向下走,走到的最深節點;要麼是start
節點往上走,某處拐彎後再到另一邊子樹的最深節點。據說這叫求二叉樹的直徑。
但是start這裏給出的只不過是一個值而已,所以要找到start節點在樹中的位置就得花一番工夫,包括找到“拐彎”總覺得有點麻煩。
常規解法還是先將樹的結構用深度優先搜索解析成無向圖,再用廣度優先搜索來求最長距離。代碼中graph
爲鄰接表,用一個哈希表來表示,哈希表的鍵爲節點值,值爲其相鄰節點的值組成的列表。
# Definition for a binary tree node.
# class TreeNode(object):
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution(object):
def amountOfTime(self, root, start):
"""
:type root: Optional[TreeNode]
:type start: int
:rtype: int
"""
# 本質上就是計算start節點到其他節點的最遠距離
# 用dfs把樹的結構解析成無向圖,用鄰接表存儲
graph = defaultdict(list)
def dfs(node):
for child in [node.left, node.right]:
if child:
graph[node.val].append(child.val)
graph[child.val].append(node.val)
dfs(child)
dfs(root)
# 用bfs求最長距離
q = deque([(start, 0)]) # (node, infection time)
visited = set([start])
time = 0
while q:
nodeVal, time = q.popleft()
for childVal in graph[nodeVal]:
if childVal not in visited:
q.append([childVal, time+1])
visited.add(childVal)
return time
複雜度分析
-
時間複雜度:O(n)O(n),其中 nn 是樹的節點個數。
-
空間複雜度:O(n)O(n)。