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.
Example 1:
Input:n = 5
, andedges = [[0,1], [0,2], [0,3], [1,4]]
Output: true
Example 2:
Input:n = 5,
andedges = [[0,1], [1,2], [2,3], [1,3], [1,4]]
Output: false
Note: 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
.
以图判树。
给定从
0
到n-1
标号的n
个结点,和一个无向边列表(每条边以结点对来表示),请编写一个函数用来判断这些边是否能够形成一个合法有效的树结构。注意:你可以假定边列表 edges 中不会出现重复的边。由于所有的边是无向边,边 [0,1] 和边 [1,0] 是相同的,因此不会同时出现在边列表 edges 中。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/graph-valid-tree
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
这道题属于图和树的综合题。给的input是节点的个数n和一些边edges,请你判断能否组成一棵树。有一个概念需要复习,树和图的区别在于图是可以有环 (cycle) 的,树不能有环;同时图的节点有可能不会连在一片,但是树的所有节点必定都是相连成一片的。对于这道题,有一些corner case需要特判,如果只有一个节点的话,那么就一定没有edges;因为题设说了不会给额外的边,所以如果边的数量 != 节点数量 - 1的话,一定不是树。
照着这个思路,我还是提供三种做法,BFS, DFS和Union Find。三种做法的时间空间复杂度都一样,union find在运行时间上可以通过路径压缩变得更快。
BFS
时间O(V * E)
空间O(n)
Java实现
1 class Solution { 2 public boolean validTree(int n, int[][] edges) { 3 // create graph 4 List<List<Integer>> graph = new ArrayList<>(); 5 for (int i = 0; i < n; i++) { 6 graph.add(new ArrayList<>()); 7 } 8 for (int i = 0; i < edges.length; i++) { 9 graph.get(edges[i][0]).add(edges[i][1]); 10 graph.get(edges[i][1]).add(edges[i][0]); 11 } 12 13 boolean[] visited = new boolean[n]; 14 Queue<Integer> queue = new LinkedList<>(); 15 queue.offer(0); 16 while (!queue.isEmpty()) { 17 int cur = queue.poll(); 18 if (visited[cur] == true) { 19 return false; 20 } 21 visited[cur] = true; 22 for (int nei : graph.get(cur)) { 23 if (!visited[nei]) { 24 queue.offer(nei); 25 } 26 } 27 } 28 29 for (int i = 0; i < n; i++) { 30 if (visited[i] == false) { 31 return false; 32 } 33 } 34 return true; 35 } 36 }
DFS
时间O(V * E)
空间O(n)
Java实现
1 class Solution { 2 public boolean validTree(int n, int[][] edges) { 3 // create graph 4 List<List<Integer>> g = new ArrayList<>(); 5 for (int i = 0; i < n; i++) { 6 g.add(new ArrayList<>()); 7 } 8 for (int[] e : edges) { 9 g.get(e[0]).add(e[1]); 10 g.get(e[1]).add(e[0]); 11 } 12 13 HashSet<Integer> visited = new HashSet<>(); 14 visited.add(0); 15 boolean res = helper(g, visited, 0, -1); 16 if (res == false) { 17 return false; 18 } 19 return visited.size() == n ? true : false; 20 } 21 22 private boolean helper(List<List<Integer>> g, HashSet<Integer> visited, int cur, int parent) { 23 List<Integer> neighbors = g.get(cur); 24 for (int nei : neighbors) { 25 if (nei == parent) { 26 continue; 27 } 28 // cycle 29 if (visited.contains(nei)) { 30 return false; 31 } 32 visited.add(nei); 33 boolean res = helper(g, visited, nei, cur); 34 if (res == false) { 35 return false; 36 } 37 } 38 return true; 39 } 40 }
Union Find
时间O(V * E)
空间O(n)
Java实现
1 class Solution { 2 public boolean validTree(int n, int[][] edges) { 3 // corner case 4 if (n == 1 && edges.length == 0) { 5 return true; 6 } 7 if (n < 1 || edges == null || edges.length != n - 1) { 8 return false; 9 } 10 11 // normal case 12 int[] roots = new int[n]; 13 for (int i = 0; i < n; i++) { 14 roots[i] = -1; 15 } 16 17 for (int[] pair : edges) { 18 int x = find(roots, pair[0]); 19 int y = find(roots, pair[1]); 20 if (x == y) { 21 return false; 22 } 23 roots[x] = y; 24 } 25 return true; 26 } 27 28 private int find(int[] roots, int i) { 29 while (roots[i] != -1) { 30 i = roots[i]; 31 } 32 return i; 33 } 34 }
相关题目