快轉到主要內容
  1. Leetcode/

[LeetCode] 310. Minimum Height Trees

·
LeetCode tree
目錄

題目連結:310. Minimum Height Trees

解題思路
#

題目要我們尋找出最小高度樹(MHT),我一開始的想法是甚麼情況下樹的高度會最高?

答案是當樹的 root 剛好為樹的直徑中的兩端點之一時樹的高度會最高。

因此如果希望找到高度最矮的樹,那可以先找到樹的直徑,再把直徑路徑(path)的中點提起來當成樹的 root 就好了,這樣子樹的高度就會是 樹的直徑 / 2

如果把直徑路徑中點以外的點提起來當成 root,那就會導致樹不平衡,一定會有一邊的高度 > 樹的直徑 / 2

要注意的是如果直徑的長度為偶數的話,那麼答案就會有兩個(因為沒辦法剛好整除),如果是奇數的話答案就只會有一個。

程式碼
#

Python
#

class Solution:
    def findMinHeightTrees(self, n: int, edges: List[List[int]]) -> List[int]:
        adj = [[] for _ in range(n)] # adjacency list
        dis = [0] * n # distance
        parent = {} # use to trace the path of diameter

        def dfs(u, prev):
            mx = u # farthest node
            parent[u] = prev
            for v in adj[u]:
                if v == prev:
                    continue
                dis[v] = dis[u] + 1
                w = dfs(v, u)
                if dis[w] > dis[mx]:
                    mx = w
            return mx

        for edge in edges:
            adj[edge[0]].append(edge[1])
            adj[edge[1]].append(edge[0])

        # perform dfs twices to find diameter
        start = dfs(0, -1)
        end = dfs(start, -1)

        # find the path of diameter
        path = []
        path.append(end)
        while parent[end] != -1:
            path.append(parent[end])
            end = parent[end]
        
        length = len(path)
        if length & 1:
            # odd
            return [path[length >> 1]]
        else:
            # even
            return [path[length >> 1], path[(length - 1) >> 1]]