zoukankan      html  css  js  c++  java
  • 判断一个图是否为普通的树

    https://leetcode.com/problems/graph-valid-tree/

    Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), write a function to check whether these edges make up a valid tree.

    For example:

    Given n = 5 and edges = [[0, 1], [0, 2], [0, 3], [1, 4]], return true.

    Given n = 5 and edges = [[0, 1], [1, 2], [2, 3], [1, 3], [1, 4]], return false.

    Hint:

    1. Given n = 5 and edges = [[0, 1], [1, 2], [3, 4]], what should your return? Is this case a valid tree?
    2. According to the definition of tree on Wikipedia: “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.”

    注意,这里的树是普通的树,不是二叉树!

    思路:要判断一个图是否为树,首先要知道树的定义。

    一棵树必须具备如下特性:

    (1)是一个全连通图(所有节点相通)

    (2)无回路

    其中(2)等价于:(3)图的边数=节点数-1

    因此我们可以利用特性(1)(2)或者(1)(3)来判断。

    方法一:广度优先搜索。要判断连通性,广度优先搜索法是一个天然的选择,时间复杂度O(n),空间复杂度O(n)。

    [java] view plain copy
     
     
    print?
    1. public class Solution {  
    2.     public boolean validTree(int n, int[][] edges) {  
    3.         Map<Integer, Set<Integer>> graph = new HashMap<>();  
    4.         for(int i=0; i<edges.length; i++) {  
    5.             for(int j=0; j<2; j++) {  
    6.                 Set<Integer> pairs = graph.get(edges[i][j]);  
    7.                 if (pairs == null) {  
    8.                     pairs = new HashSet<>();  
    9.                     graph.put(edges[i][j], pairs);  
    10.                 }  
    11.                 pairs.add(edges[i][1-j]);  
    12.             }  
    13.         }  
    14.         Set<Integer> visited = new HashSet<>();  
    15.         Set<Integer> current = new HashSet<>();  
    16.         visited.add(0);  
    17.         current.add(0);  
    18.         while (!current.isEmpty()) {  
    19.             Set<Integer> next = new HashSet<>();  
    20.             for(Integer node: current) {  
    21.                 Set<Integer> pairs = graph.get(node);  
    22.                 if (pairs == null) continue;  
    23.                 for(Integer pair: pairs) {  
    24.                     if (visited.contains(pair)) return false;  
    25.                     next.add(pair);  
    26.                     visited.add(pair);  
    27.                     graph.get(pair).remove(node);  
    28.                 }  
    29.             }  
    30.             current = next;  
    31.         }  
    32.         return visited.size() == n;  
    33.     }  
    34. }  
    public class Solution {
        public boolean validTree(int n, int[][] edges) {
            Map<Integer, Set<Integer>> graph = new HashMap<>();
            for(int i=0; i<edges.length; i++) {
                for(int j=0; j<2; j++) {
                    Set<Integer> pairs = graph.get(edges[i][j]);
                    if (pairs == null) {
                        pairs = new HashSet<>();
                        graph.put(edges[i][j], pairs);
                    }
                    pairs.add(edges[i][1-j]);
                }
            }
            Set<Integer> visited = new HashSet<>();
            Set<Integer> current = new HashSet<>();
            visited.add(0);
            current.add(0);
            while (!current.isEmpty()) {
                Set<Integer> next = new HashSet<>();
                for(Integer node: current) {
                    Set<Integer> pairs = graph.get(node);
                    if (pairs == null) continue;
                    for(Integer pair: pairs) {
                        if (visited.contains(pair)) return false;
                        next.add(pair);
                        visited.add(pair);
                        graph.get(pair).remove(node);
                    }
                }
                current = next;
            }
            return visited.size() == n;
        }
    }

    方法二:深度优先搜索,搜索目标是遍历全部节点。参考文章:http://buttercola.blogspot.com/2015/08/leetcode-graph-valid-tree.html

    [java] view plain copy
     
     
    print?
    1. public class Solution {  
    2.     private boolean[] visited;  
    3.     private int visits = 0;  
    4.     private boolean isTree = true;  
    5.     private void check(int prev, int curr, List<Integer>[] graph) {  
    6.         if (!isTree) return;  
    7.         if (visited[curr]) {  
    8.             isTree = false;  
    9.             return;  
    10.         }  
    11.         visited[curr] = true;  
    12.         visits ++;  
    13.         for(int next: graph[curr]) {  
    14.             if (next == prev) continue;  
    15.             check(curr, next, graph);  
    16.             if (!isTree) return;  
    17.         }  
    18.           
    19.     }  
    20.     public boolean validTree(int n, int[][] edges) {  
    21.         visited = new boolean[n];  
    22.         List<Integer>[] graph = new List[n];  
    23.         for(int i=0; i<n; i++) graph[i] = new ArrayList<>();  
    24.         for(int[] edge: edges) {  
    25.             graph[edge[0]].add(edge[1]);  
    26.             graph[edge[1]].add(edge[0]);  
    27.         }  
    28.         check(-1, 0, graph);  
    29.         return isTree && visits == n;  
    30.     }  
    31. }  
    public class Solution {
        private boolean[] visited;
        private int visits = 0;
        private boolean isTree = true;
        private void check(int prev, int curr, List<Integer>[] graph) {
            if (!isTree) return;
            if (visited[curr]) {
                isTree = false;
                return;
            }
            visited[curr] = true;
            visits ++;
            for(int next: graph[curr]) {
                if (next == prev) continue;
                check(curr, next, graph);
                if (!isTree) return;
            }
            
        }
        public boolean validTree(int n, int[][] edges) {
            visited = new boolean[n];
            List<Integer>[] graph = new List[n];
            for(int i=0; i<n; i++) graph[i] = new ArrayList<>();
            for(int[] edge: edges) {
                graph[edge[0]].add(edge[1]);
                graph[edge[1]].add(edge[0]);
            }
            check(-1, 0, graph);
            return isTree && visits == n;
        }
    }

    方法三:按节点大小对边进行排序,原理类似并查集。

    [java] view plain copy
     
     
    print?
    1. public class Solution {  
    2.     public boolean validTree(int n, int[][] edges) {  
    3.         if (edges.length != n-1) return false;  
    4.         Arrays.sort(edges, new Comparator<int[]>() {  
    5.            @Override  
    6.            public int compare(int[] e1, int[] e2) {  
    7.                return e1[0] - e2[0];  
    8.            }  
    9.         });  
    10.         int[] sets = new int[n];  
    11.         for(int i=0; i<n; i++) sets[i] = i;  
    12.         for(int i=0; i<edges.length; i++) {  
    13.             if (sets[edges[i][0]] == sets[edges[i][1]]) return false;  
    14.             if (sets[edges[i][0]] == 0) {  
    15.                 sets[edges[i][1]] = 0;  
    16.             } else if (sets[edges[i][1]] == 0) {  
    17.                 sets[edges[i][0]] = 0;  
    18.             } else {  
    19.                 sets[edges[i][1]] = sets[edges[i][0]];  
    20.             }  
    21.         }  
    22.         return true;  
    23.     }  
    24. }  
    public class Solution {
        public boolean validTree(int n, int[][] edges) {
            if (edges.length != n-1) return false;
            Arrays.sort(edges, new Comparator<int[]>() {
               @Override
               public int compare(int[] e1, int[] e2) {
                   return e1[0] - e2[0];
               }
            });
            int[] sets = new int[n];
            for(int i=0; i<n; i++) sets[i] = i;
            for(int i=0; i<edges.length; i++) {
                if (sets[edges[i][0]] == sets[edges[i][1]]) return false;
                if (sets[edges[i][0]] == 0) {
                    sets[edges[i][1]] = 0;
                } else if (sets[edges[i][1]] == 0) {
                    sets[edges[i][0]] = 0;
                } else {
                    sets[edges[i][1]] = sets[edges[i][0]];
                }
            }
            return true;
        }
    }

    方法四:Union-Find

    [java] view plain copy
     
     
    print?
    1. public class Solution {  
    2.     public boolean validTree(int n, int[][] edges) {  
    3.         if (edges.length != n-1) return false;  
    4.         int[] roots = new int[n];  
    5.         for(int i=0; i<n; i++) roots[i] = i;  
    6.         for(int i=0; i<edges.length; i++) {  
    7.             int root1 = root(roots, edges[i][0]);  
    8.             int root2 = root(roots, edges[i][1]);  
    9.             if (root1 == root2) return false;  
    10.             roots[root2] = root1;  
    11.         }  
    12.         return true;  
    13.     }  
    14.     private int root(int[] roots, int id) {  
    15.         if (id == roots[id]) return id;  
    16.         return root(roots, roots[id]);  
    17.     }  
    18. }  
  • 相关阅读:
    209. Minimum Size Subarray Sum
    208. Implement Trie (Prefix Tree)
    207. Course Schedule
    206. Reverse Linked List
    205. Isomorphic Strings
    204. Count Primes
    203. Remove Linked List Elements
    201. Bitwise AND of Numbers Range
    199. Binary Tree Right Side View
    ArcGIS API for JavaScript 4.2学习笔记[8] 2D与3D视图同步
  • 原文地址:https://www.cnblogs.com/mdumpling/p/9142410.html
Copyright © 2011-2022 走看看