310. Minimum Height Trees

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.

Format
The graph contains n nodes which are labeled from 0 to n - 1. You will be given the number n and a list of undirected edges (each edge is a pair of labels).
You can assume that no duplicate edges will appear in edges. Since all edges are undirected, [0, 1] is the same as [1, 0] and thus will not appear together in edges.

Example 1:
Given n = 4, edges = [[1, 0], [1, 2], [1, 3]]

        0
        |
        1
       / \
      2   3
return [1]
Example 2:
Given n = 6, edges = [[0, 3], [1, 3], [2, 3], [4, 3], [5, 4]]

     0  1  2
      \ | /
        3
        |
        4
        |
        5
return [3, 4]

Note:
(1) According to the definition of tree on Wikipedia: “a tree is an undirected graph in which any two vertices are connected by exactlyone path. In other words, any connected graph without simple cycles is a tree.”
(2) The height of a rooted tree is the number of edges on the longest downward path between the root and a leaf.

Solution1:Literally find Longest Path by BFS

思路: 随便选一点a,从a bfs先找出距a的最远的u,再从u点bfs找出最远点v,u到v的path的一半处就是result.
Time Complexity: O(N) Space Complexity: O(N)
Note: DFS 1.b 这这里其实也可以

Solution2:BFS topological sort

思路: 类似Undirected拓扑排序对策BFS方法,从pointers所有leaves向内,当两个pointers met,only keep one of them, until the last two pointers meet or one step away we then find the roots.

(1) 在做UnDirected 拓扑排序时,要避免访问前驱:
实现1:采用在adj_list.get(cur).remove(prev)的方式,因为(1),所以remove是O(1), 且这样就不需要使用indegree数组,adj_list.get(cur).size()就可以作为indegree作用。
(实现2: 不remove,通过visited数组,但额外需要indegree数组,因为adj_list.get(cur).size()不能再作为indegree作用。可以indegree数组/visited数组通过共同一个数组表示。)因为下述(2),肯定是访问到的是 prev->cur->next形式,所以remove是O(1),实现1比较好

(2) 在做UnDirected 拓扑排序时,访问到的indegree = 1的node,最多肯定只有一个前驱和一个后继,所以不需要遍历list来拿到nexts,只有一个next,直接可以通过adj.get(u).iterator().next();

We start from every end, by end we mean vertex of degree 1 (aka leaves). We let the pointers move the same speed. When two pointers meet, we keep only one of them, until the last two pointers meet or one step away we then find the roots.
It is easy to see that the last two pointers are from the two ends of the longest path in the graph.
The actual implementation is similar to the BFS topological sort. Remove the leaves, update the degrees of inner vertexes. Then remove the new leaves. Doing so level by level until there are 2 or 1 nodes left. What's left is our answer!

Time Complexity: O(N) Space Complexity: O(N)

Solution3:Tree DP??

思路: (temporarily skip)
reference: https://leetcode.com/problems/minimum-height-trees/discuss/
Time Complexity: O(N) Space Complexity: O(N)

Solution1 Code:

public class Solution {
    int n;
    List> graph;

    public List findMinHeightTrees(int n, int[][] edges) {
        if (n <= 0) return new ArrayList<>();
        this.n = n;
        
        // build graph
        graph = new ArrayList>();
        for(int i = 0; i < n; i++) {
            graph.add(new ArrayList());
        }
        for (int[] pair : edges) {
            int u = pair[0];
            int v = pair[1];
            graph.get(u).add(v);
            graph.get(v).add(u);
        }
        
        int[] dist1 = new int[n]; // dist for all node from u
        int[] dist2 = new int[n]; // dist for all node from v
        int[] pre = new int[n]; // precursor array: v: u
        
        // get far end1 = u
        bfs(0, dist1, pre);
        int u = 0;
        for (int i = 0; i < n; i++)
            if (dist1[i] > dist1[u]) u = i;

        // get far end2 = v
        bfs(u, dist2, pre);
        int v = 0;
        for (int i = 0; i < n; i++)
            if (dist2[i] > dist2[v]) v = i;

        // prepare the result: add path from u to v to list
        List list = new ArrayList<>();
        while (v != -1) {
            list.add(v);
            v = pre[v];
        }

        // return the result
        if (list.size() % 2 == 1) return Arrays.asList(list.get(list.size() / 2));
        else return Arrays.asList(list.get(list.size() / 2 - 1), list.get(list.size() / 2));
    }
    
    
    private void bfs(int start, int[] dist, int[] pre) {
        boolean[] visited = new boolean[n];
        Queue queue = new LinkedList<>();
        
        queue.add(start);
        visited[start] = true;
        dist[start] = 0;
        pre[start] = -1;
        while (!queue.isEmpty()) {
            int u = queue.poll();
            for (int v : graph.get(u))
                if (!visited[v]) {
                    dist[v] = dist[u] + 1;
                    queue.add(v);
                    visited[start] = true;
                    pre[v] = u;
                }
        }
    }
}

Solution1.b Code:

class Solution {
    
    class Pack {
        public int far_id;
        public int max_len;
        
        Pack() {
            far_id = -1;
            max_len = 0;
        }
    }

    public List findMinHeightTrees(int n, int[][] edges) {
        if(edges == null || edges.length == 0) {
            if(n == 1) return Arrays.asList(0);
            else return new ArrayList<>();
        }
        
        // graph
        List> graph = new ArrayList<>();
        for(int i = 0; i < n; i++) {
            graph.add(new ArrayList<>());
        }
        for(int i = 0; i < edges.length; i++) {
            graph.get(edges[i][0]).add(edges[i][1]);
            graph.get(edges[i][1]).add(edges[i][0]);
        }
        
        int[] pre = new int[n];
        Arrays.fill(pre, -1);
        
        Pack pack1 = dfs(graph, edges[0][0], -1, pre);
        Pack pack2 = dfs(graph, pack1.far_id, -1, pre);
        
        List list = new ArrayList<>();
        
        pack1.max_len -= 1;
        pack2.max_len -= 1;

        int v = pack2.far_id;
        while (v != -1) {
            System.out.println("v: " + v);
            list.add(v);
            v = pre[v];
        }
        
        // prepare result
        if(list.size() % 2 == 1) {
            return Arrays.asList(list.get(list.size() / 2));
        }
        else {
            return Arrays.asList(list.get(list.size() / 2 - 1), list.get(list.size() / 2));
        }
    }
    
    
    private Pack dfs(List> graph, int start_id, int prev, int[] pre) {
        Pack cur_pack = new Pack();
        if(graph.get(start_id).size() == 1) {
            // leaf
            cur_pack.far_id = start_id;
        }
        pre[start_id] = prev;
        
        List next_list = graph.get(start_id);
        for(int next: next_list) {
            if(next == prev) continue;
            Pack pack = dfs(graph, next, start_id, pre);
            if(pack.max_len > cur_pack.max_len) {
                cur_pack.max_len = pack.max_len;
                cur_pack.far_id = pack.far_id;
            }
        }
        
        cur_pack.max_len++;
        return cur_pack;
    }
}

Solution2 Code:

public class Solution {
    public List findMinHeightTrees(int n, int[][] edges) {
        if (n == 1) return Arrays.asList(0);
        // if (n == 2) return Arrays.asList(0, 1);
        
        // graph: adj_list init
        List> adj = new ArrayList>();
        for(int i = 0; i < n; i++) {
            adj.add(new ArrayList()); 
        }
        for (int[] edge : edges) {
            adj.get(edge[0]).add(edge[1]);
            adj.get(edge[1]).add(edge[0]);
        }
        

        Queue leaves = new LinkedList<>();
        for (int i = 0; i < n; ++i) {
            if (adj.get(i).size() == 1) leaves.offer(i);
        }
        
        while (n > 2) {
            int num_leaves = leaves.size();
            n -= num_leaves;
            for(int i = 0; i < num_leaves; i++) {
                int u = leaves.poll();
                int v = adj.get(u).iterator().next();
                adj.get(v).remove(new Integer(u)); // remove by finding value.
                if (adj.get(v).size() == 1) leaves.add(v);
            }
        }
        return (List)leaves;
    }

}

Solution3 Code:

你可能感兴趣的:(310. Minimum Height Trees)