1 minute read

Problem Statement

problem-310

BFS Approach - TLE

class Solution:
    def findMinHeightTrees(self, n: int, edges: List[List[int]]) -> List[int]:
        graph = {i: [] for i in range(n)}
        for x, y in edges:
            graph[x].append(y)
            graph[y].append(x)

        def bfs(node):
            queue = deque([[node, 0]])
            height = float('-inf')
            visited = set()
            visited.add(node)
            while queue:
                curr, level = queue.popleft()
                isLeaf = True
                for nei in graph[curr]:
                    if nei not in visited:
                        queue.append([nei, level + 1])
                        visited.add(nei)
                        isLeaf = False
                if isLeaf:
                    height = max(height, level)

            return height

        heights = []
        for i in range(n):
            heights.append(bfs(i))

        res = []
        min_height = min(heights)
        for i, height in enumerate(heights):
            if height == min_height:
                res.append(i)
        return res
  • Time: O(n^2)
  • Space: O(n)

Editorial Solution

Topological Sorting

class Solution:
    def findMinHeightTrees(self, n: int, edges: List[List[int]]) -> List[int]:

        # edge cases
        if n <= 2:
            return [i for i in range(n)]

        # Build the graph with the adjacency list
        neighbors = [set() for i in range(n)]
        for start, end in edges:
            neighbors[start].add(end)
            neighbors[end].add(start)

        # Initialize the first layer of leaves
        leaves = []
        for i in range(n):
            if len(neighbors[i]) == 1:
                leaves.append(i)

        # Trim the leaves until reaching the centroids
        remaining_nodes = n
        while remaining_nodes > 2:
            remaining_nodes -= len(leaves)
            new_leaves = []
            # remove the current leaves along with the edges
            while leaves:
                leaf = leaves.pop()
                # the only neighbor left for the leaf node
                neighbor = neighbors[leaf].pop()
                # remove the only edge left
                neighbors[neighbor].remove(leaf)
                if len(neighbors[neighbor]) == 1:
                    new_leaves.append(neighbor)

            # prepare for the next round
            leaves = new_leaves

        # The remaining nodes are the centroids of the graph
        return leaves
  • Time: O(V) where V is the number of nodes in graph
  • Space: O(V)