LeetCode Minimum Height Trees

Description:

For a undirected graph with tree characteristics, we can choose any node as the root. The result graph is then a rooted tree. Among all possible rooted trees, those with minimum height are called minimum height trees (MHTs). Given such a graph, write a function to find all the MHTs and return a list of their root labels.

Solution:

Change this problem to finding the diameter of a tree, and use two dfs can solve it.

Use three arrays, first[], firstFrom[], and second[].

first[i] is the longest path started from node i.

second[i] is the second path started from node i.

firstFrom[i] is the where the longest path from i lead to.


Two dfs:

1. DownToUp: this if the first dfs. The task here is start from any node (I use 0 here), and calculate each node first, firstFrom, and second considering only the nodes that are child node.

2. UpToDown: since we have known the first, and second for each node of its child node, then we need to consider its parent node. (and that is why we need firstFrom and dfs from Up to Down)


import java.util.*;

public class Solution {

	int n;
	int head[];
	edge edges[];
	int tot = 0;
	int[] first;
	int[] firstFrom;
	int[] second;
	boolean[] visit;

	public void addEdges(int u, int v) {
		edges[tot] = new edge(v);
		edges[tot].next = head[u];
		head[u] = tot++;
	}

	public List<Integer> findMinHeightTrees(int n, int[][] edges) {
		List<Integer> list = new LinkedList<Integer>();

		this.n = n;
		this.head = new int[n];
		Arrays.fill(this.head, -1);
		this.edges = new edge[n * 3];
		this.first = new int[n];
		this.second = new int[n];
		this.firstFrom = new int[n];
		this.visit = new boolean[n];

		for (int i = 0; i < n - 1; i++) {
			int u = edges[i][0];
			int v = edges[i][1];
			addEdges(u, v);
			addEdges(v, u);
		}

		Arrays.fill(visit, false);
		visit[0] = true;
		dfsDownToTop(0);

		Arrays.fill(visit, false);
		dfsTopToDown(0);

		int min = n;
		for (int i = 0; i < n; i++) {
			if (first[i] < min) {
				min = first[i];
				list.clear();
				list.add(i);
			} else if (first[i] == min) {
				list.add(i);
			}
		}

		return list;
	}

	public void dfsDownToTop(int u) {
		for (int e = head[u]; e != -1; e = edges[e].next) {
			int v = edges[e].v;
			if (visit[v])
				continue;
			visit[v] = true;
			dfsDownToTop(v);
			if (first[v] + 1 > first[u]) {
				second[u] = first[u];
				first[u] = first[v] + 1;
				firstFrom[u] = v;
			} else if (first[v] + 1 >= second[u]) {
				if (first[v] + 1 == first[u])
					firstFrom[u] = -1;
				second[u] = first[v] + 1;
			}
		}
		return;
	}

	public void dfsTopToDown(int u) {
		int len;
		for (int e = head[u]; e != -1; e = edges[e].next) {
			int v = edges[e].v;
			if (visit[v])
				continue;
			if (firstFrom[u] == v)
				len = second[u] + 1;
			else
				len = first[u] + 1;
			if (len > first[v]) {
				second[v] = first[v];
				first[v] = len;
				firstFrom[v] = u;
			} else if (len == first[v]) {
				firstFrom[v] = -10;
				second[v] = len;
			} else if (len > second[v])
				second[v] = len;
		}
		for (int e = head[u]; e != -1; e = edges[e].next) {
			int v = edges[e].v;
			if (visit[v])
				continue;
			visit[v] = true;
			dfsTopToDown(v);
		}
		return;
	}

	class edge {
		int v;
		int next;

		edge(int v) {
			this.v = v;
			next = -1;
		}
	}
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值