【每日一題】感染二叉樹需要的總時間

2385. 感染二叉樹需要的總時間

給你一棵二叉樹的根節點 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)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章