Talentd
FleetCode
Make and follow sheets.Sign in

Minimum Height Trees solution and explanation

MediumBreadth-First SearchDepth-First SearchGraphTopological Sort6 min read42.4% acceptanceUpdated 9 Apr 2026
Minimum Height Trees - Leetcode 310 - PythonNeetCodeIO · 23:30 · 43K viewsWatch on YouTube
9 more videos on this problem
  1. Minimum Height Trees - Leetcode 310 - PythonNeetCodeIO · 23:30 · 43K views
  2. Minimum Height Trees | Live Coding with Explanation | Leetcode #310Algorithms Made Easy · 9:38 · 33K views
  3. Minimum Height Trees | LeetCode 310 | C++, Java, PythonKnowledge Center · 24:19 · 17K views
  4. 310. Minimum Height Trees | BFS | Topological Sort | GraphsAryan Mittal · 24:47 · 10K views
  5. Minimum Height Trees 🔥🔥| Leetcode 310 | BFSAyushi Sharma · 26:28 · 10K views
  6. 310 Minimum Height Trees -- Leetcodeelidrinkscoffee · 9:43 · 5K views
  7. Minimum Height Trees | Leetcode 310 | Live coding session 🔥🔥🔥 | BFS traversalCoding Decoded · 10:44 · 3K views
  8. Minimum Height Trees - Leetcode 310Harsh Agrawal · 21:07 · 1K views
  9. Daily Leetcode #1484: Apr 23, 2024 - 310. Minimum Height TreesProgramming Live with Larry · 23:41 · 985 views
  10. LeetCode 310. Minimum Height Trees Solution w/Java - Coding Interview Question( Facebook,Google)Dev Sheriff · 5:20 · 944 views

The problem

A tree is an undirected graph in which any two vertices are connected by exactly one path. In other words, any connected graph without simple cycles is a tree.

Given a tree of n nodes labelled from 0 to n - 1, and an array of n - 1 edges where edges[i] = [ai, bi] indicates that there is an undirected edge between the two nodes ai and bi in the tree, you can choose any node of the tree as the root. When you select a node x as the root, the result tree has height h. Among all possible rooted trees, those with minimum height (i.e. min(h))  are called minimum height trees (MHTs).

Return a list of all MHTs' root labels. You can return the answer in any order.

The height of a rooted tree is the number of edges on the longest downward path between the root and a leaf.

Example 1:

Input: n = 4, edges = [[1,0],[1,2],[1,3]]
Output: [1]
Explanation: As shown, the height of the tree is 1 when the root is the node with label 1 which is the only MHT.

Example 2:

Input: n = 6, edges = [[3,0],[3,1],[3,2],[3,4],[5,4]]
Output: [3,4]

Constraints:

  • 1 <= n <= 2 * 104
  • edges.length == n - 1
  • 0 <= ai, bi < n
  • ai != bi
  • All the pairs (ai, bi) are distinct.
  • The given input is guaranteed to be a tree and there will be no repeated edges.

Approach overview

Problem Overview: You are given an undirected tree with n nodes labeled from 0 to n-1. Any node can be chosen as the root. The task is to return all nodes that produce a tree with the minimum possible height when used as the root.

Approach 1: Trim the Leaves Iteratively (Topological BFS) (Time: O(n), Space: O(n))

This approach treats the tree like an onion and repeatedly removes outer layers. Start by building an adjacency list and tracking the degree of each node. All nodes with degree 1 are leaves. Push these leaves into a queue and remove them level by level while updating the degree of their neighbors. When a neighbor’s degree becomes 1, it becomes a new leaf and enters the queue. Continue until only one or two nodes remain. Those remaining nodes are the centroids of the tree and represent valid Minimum Height Tree roots. The key insight: the center of a tree remains after peeling away leaves. This process mirrors topological sort applied to an undirected tree and uses a standard breadth-first search queue.

Approach 2: Utilize Two BFS Runs (Tree Diameter Method) (Time: O(n), Space: O(n))

A Minimum Height Tree root must lie at the center of the tree’s diameter. First run BFS from any node (commonly node 0) to find the farthest node A. Then run another BFS from A to find the farthest node B. The path from A to B is the diameter of the tree. The middle node (or two middle nodes if the diameter length is even) forms the Minimum Height Tree roots. During the second BFS, track parent pointers so you can reconstruct the diameter path. This method relies on properties of trees and repeated graph traversal.

Recommended for interviews: The iterative leaf trimming method is the approach most interviewers expect. It directly models the idea of shrinking the tree toward its center and runs in linear time O(n). The two-BFS diameter approach is also optimal and demonstrates strong understanding of tree properties. Showing awareness of both approaches signals strong graph fundamentals.

Approach 1: Trim the Leaves Iteratively

This approach uses an iterative method to trim the leaf nodes layer by layer until you are left with the centermost nodes, which are the roots of the Minimum Height Trees.

The idea is similar to peeling layers of an onion from the outside to the inside. The process stops when there are no more than two nodes left.

#include <vector>
#include <queue>
using namespace std;

vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) {
    if (n == 1) return {0};

    vector<int> degree(n, 0);
    vector<vector<int>> adj(n);

    for (const auto& edge : edges) {
        adj[edge[0]].push_back(edge[1]);
        adj[edge[1]].push_back(edge[0]);
        degree[edge[0]]++;
        degree[edge[1]]++;
    }

    queue<int> leaves;
    for (int i = 0; i < n; i++) {
        if (degree[i] == 1) leaves.push(i);
    }

    int count = n;
    while (count > 2) {
        int size = leaves.size();
        count -= size;

        for (int i = 0; i < size; i++) {
            int leaf = leaves.front();
            leaves.pop();
            degree[leaf]--;

            for (int neighbor : adj[leaf]) {
                if (--degree[neighbor] == 1) {
                    leaves.push(neighbor);
                }
            }
        }
    }

    vector<int> result;
    while (!leaves.empty()) {
        result.push_back(leaves.front());
        leaves.pop();
    }

    return result;
}
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>

#define MAX_NODES 20000

int* findMinHeightTrees(int n, int** edges, int edgesSize, int* edgesColSize, int* returnSize){
    if (n == 1) {
        *returnSize = 1;
        int* res = (int*)malloc(sizeof(int));
        res[0] = 0;
        return res;
    }
    
    int* degrees = (int*)calloc(n, sizeof(int));
    int* adj[MAX_NODES];
    for (int i = 0; i < n; ++i) adj[i] = (int*)malloc(sizeof(int) * n);
    int adjLen[MAX_NODES] = {0};

    for (int i = 0; i < edgesSize; ++i) {
        int u = edges[i][0], v = edges[i][1];
        adj[u][adjLen[u]++] = v;
        adj[v][adjLen[v]++] = u;
        degrees[u]++;
        degrees[v]++;
    }
    
    int queue[MAX_NODES];
    int front = 0, rear = 0;
    for (int i = 0; i < n; ++i) {
        if (degrees[i] == 1) {
            queue[rear++] = i;
        }
    }

    int count = n;
    while (count > 2) {
        int size = rear - front;
        count -= size;
        for (int i = 0; i < size; ++i) {
            int leaf = queue[front++];
            degrees[leaf]--;
            for (int j = 0; j < adjLen[leaf]; ++j) {
                int neighbor = adj[leaf][j];
                if (--degrees[neighbor] == 1) {
                    queue[rear++] = neighbor;
                }
            }
        }
    }

    *returnSize = rear - front;
    int* res = (int*)malloc((*returnSize) * sizeof(int));
    for (int i = 0; front < rear; ++front, ++i) {
        res[i] = queue[front];
    }
    
    free(degrees);
    for (int i = 0; i < n; ++i) free(adj[i]);

    return res;
}

The C++ code uses a queue to iteratively remove leaves, reducing the graph till potential centroids are found. It leverages vectors for adjacency list creation and manages the node degree.

Complexity

Time Complexity: O(n), each node and edge is considered once.
Space Complexity: O(n), for the graph representation and degree management.

Try this approach in the editor

Approach 2: Utilize Two BFS Runs

This technique applies two breadth-first searches (BFS). Start from any node, find the farthest node to determine a tree diameter. From this end node, perform another BFS to determine the second endpoint. The center of the path between these endpoints, which are the potential MHT roots, is found.

from collections import defaultdict, deque

def findMinHeightTrees(n, edges):
    if n == 1:
        return [0]

    adj = defaultdict(set)
    for u, v in edges:
        adj[u].add(v)
        adj[v].add(u)

    leaves = deque(i for i in range(n) if len(adj[i]) == 1)

    while n > 2:
        n -= len(leaves)
        new_leaves = deque()
        while leaves:
            leaf = leaves.popleft()
            for neighbor in adj[leaf]:
                adj[neighbor].remove(leaf)
                if len(adj[neighbor]) == 1:
                    new_leaves.append(neighbor)
            adj.pop(leaf)
        leaves = new_leaves

    return list(leaves)
import java.util.*;

class Solution {
    public List<Integer> findMinHeightTrees(int n, int[][] edges) {
        if (n == 1) return Collections.singletonList(0);

        List<Set<Integer>> adj = new ArrayList<>(n);
        for (int i = 0; i < n; i++) adj.add(new HashSet<>());
        for (int[] edge : edges) {
            adj.get(edge[0]).add(edge[1]);
            adj.get(edge[1]).add(edge[0]);
        }

        int[] degree = new int[n];
        for (int i = 0; i < n; i++) degree[i] = adj.get(i).size();

        Queue<Integer> leaves = new ArrayDeque<>();
        for (int i = 0; i < n; i++) {
            if (degree[i] == 1) leaves.offer(i);
        }

        while (n > 2) {
            int size = leaves.size();
            n -= size;
            for (int i = 0; i < size; i++) {
                int leaf = leaves.poll();
                for (int neighbor : adj.get(leaf)) {
                    adj.get(neighbor).remove(leaf);
                    if (--degree[neighbor] == 1) leaves.offer(neighbor);
                }
            }
        }

        return new ArrayList<>(leaves);
    }
}

This Python implementation uses adjacency sets and deque to handle the leaf removal process, eventually finding the MHT roots.

Complexity

Time Complexity: O(n), for iterating and modifying across all nodes.
Space Complexity: O(n), to store adjacency data and queue information.

Try this approach in the editor

Approach 3: Topological Sorting

If the tree only has one node, then this node is the root of the minimum height tree. We can directly return this node.

If the tree has multiple nodes, there must be leaf nodes. A leaf node is a node that only has one adjacent node. We can use topological sorting to peel off the leaf nodes from the outside to the inside. When we reach the last layer, the remaining nodes are the root nodes of the minimum height tree.

The time complexity is O(n) and the space complexity is O(n), where n is the number of nodes.

function findMinHeightTrees(n: number, edges: number[][]): number[] {
    if (n === 1) {
        return [0];
    }
    const g: number[][] = Array.from({ length: n }, () => []);
    const degree: number[] = Array(n).fill(0);
    for (const [a, b] of edges) {
        g[a].push(b);
        g[b].push(a);
        ++degree[a];
        ++degree[b];
    }
    const q: number[] = [];
    for (let i = 0; i < n; ++i) {
        if (degree[i] === 1) {
            q.push(i);
        }
    }
    const ans: number[] = [];
    while (q.length > 0) {
        ans.length = 0;
        const t: number[] = [];
        for (const a of q) {
            ans.push(a);
            for (const b of g[a]) {
                if (--degree[b] === 1) {
                    t.push(b);
                }
            }
        }
        q.splice(0, q.length, ...t);
    }
    return ans;
}
func findMinHeightTrees(n int, edges [][]int) (ans []int) {
	if n == 1 {
		return []int{0}
	}
	g := make([][]int, n)
	degree := make([]int, n)
	for _, e := range edges {
		a, b := e[0], e[1]
		g[a] = append(g[a], b)
		g[b] = append(g[b], a)
		degree[a]++
		degree[b]++
	}
	q := []int{}
	for i, d := range degree {
		if d == 1 {
			q = append(q, i)
		}
	}
	for len(q) > 0 {
		ans = []int{}
		for i := len(q); i > 0; i-- {
			a := q[0]
			q = q[1:]
			ans = append(ans, a)
			for _, b := range g[a] {
				degree[b]--
				if degree[b] == 1 {
					q = append(q, b)
				}
			}
		}
	}
	return
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
Trim the Leaves Iteratively

Time Complexity: O(n), each node and edge is considered once.
Space Complexity: O(n), for the graph representation and degree management.

Utilize Two BFS Runs

Time Complexity: O(n), for iterating and modifying across all nodes.
Space Complexity: O(n), to store adjacency data and queue information.

Topological Sorting–

Complexity analysis

ApproachTimeSpaceWhen to Use
Trim the Leaves Iteratively (Topological BFS)O(n)O(n)Best general solution for Minimum Height Trees; commonly expected in interviews
Two BFS Runs (Tree Diameter)O(n)O(n)Useful when analyzing tree diameter or when BFS traversal logic is already implemented

Frequently asked questions

Is Minimum Height Trees easy or hard?

Minimum Height Trees is rated Medium on LeetCode. The challenge is recognizing that the root must lie at the center of the tree. Once you understand the centroid property, the BFS leaf trimming solution becomes straightforward.

How to solve Minimum Height Trees in O(n)?

Use the leaf trimming technique. Build an adjacency list and track the degree of every node. Push all leaves (degree = 1) into a queue and remove them level by level while updating neighbor degrees. Continue until at most two nodes remain; those nodes are the Minimum Height Tree roots.

What is the best approach for Minimum Height Trees?

The most widely used approach is trimming leaves iteratively using a BFS queue. By repeatedly removing nodes with degree 1, the tree shrinks toward its center. The remaining one or two nodes are the centroids that produce minimum height. This method runs in O(n) time and O(n) space.

Is Minimum Height Trees asked at Google/Amazon/Meta?

Minimum Height Trees is a common graph interview question and has appeared in coding interviews at companies like Amazon, Google, and Meta. It tests understanding of tree properties, BFS traversal, and graph center concepts.

What data structure is used in Minimum Height Trees?

The typical solution uses an adjacency list to represent the graph and a queue for BFS processing. Additional arrays track node degrees and parent relationships. These structures allow efficient traversal and leaf removal in linear time.

What is the time complexity of Minimum Height Trees?

Optimal solutions run in O(n) time where n is the number of nodes. Each edge and node is processed at most once while building the adjacency list and performing BFS or leaf trimming. Space complexity is also O(n) due to the adjacency list and queue structures.

Minimum Height Trees Python or Java solution approach?

Both Python and Java implementations typically use the leaf trimming BFS strategy. Build an adjacency list, compute node degrees, enqueue all leaves, and repeatedly remove them until one or two nodes remain. The same O(n) algorithm translates cleanly across both languages.

Comments

Now write it yourselfClose this page and solve Minimum Height Trees in the editor, without looking.
Practise Minimum Height Trees