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
.
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
.
1 public class Solution { 2 // union find: http://www.geeksforgeeks.org/union-find/ 3 public bool ValidTree(int n, int[,] edges) { 4 if (edges.GetLength(0) != n - 1) return false; 5 6 var parent = new int[n]; 7 for (int i = 0; i < n; i++) 8 { 9 parent[i] = -1; 10 } 11 12 for (int i = 0; i < edges.GetLength(0); i++) 13 { 14 int x = Find(parent, edges[i, 0]); 15 int y = Find(parent, edges[i, 1]); 16 17 if (x == y) 18 { 19 return false; 20 } 21 22 Union(parent, x, y); 23 } 24 25 return true; 26 } 27 28 private int Find(int[] parent, int i) 29 { 30 if (parent[i] == -1) 31 { 32 return i; 33 } 34 35 return Find(parent, parent[i]); 36 } 37 38 private void Union(int[] parent, int i, int j) 39 { 40 parent[i] = j; 41 } 42 } 43 44 // bfs 45 public class Solution1 { 46 public bool ValidTree(int n, int[,] edges) { 47 var adjacentList = new IList<int>[n]; 48 49 // we need to add the edges twice as the graph is undirected and if we don't add twice, we won't be able traverse it. 50 // But when we do BFS/DFS, we need to make sure to traverse the same edge more than once 51 for (int i = 0; i < edges.GetLength(0); i++) 52 { 53 if (adjacentList[edges[i, 0]] == null) 54 { 55 adjacentList[edges[i, 0]] = new List<int>(); 56 } 57 58 adjacentList[edges[i, 0]].Add(edges[i, 1]); 59 60 if (adjacentList[edges[i, 1]] == null) 61 { 62 adjacentList[edges[i, 1]] = new List<int>(); 63 } 64 65 adjacentList[edges[i, 1]].Add(edges[i, 0]); 66 } 67 68 var visited = new int[n]; 69 var queue = new Queue<int>(); 70 queue.Enqueue(0); 71 72 // there are three states of visited, 0 means not visited, 1 means visiting, 2 means visited 73 visited[0] = 1; 74 75 while (queue.Count > 0) 76 { 77 var cur = queue.Dequeue(); 78 79 if (adjacentList[cur] != null) 80 { 81 foreach (var c in adjacentList[cur]) 82 { 83 if (visited[c] == 1) return false; 84 if (visited[c] == 0) 85 { 86 visited[c] = 1; 87 queue.Enqueue(c); 88 } 89 } 90 } 91 92 visited[cur] = 2; 93 } 94 95 for (int i = 0; i < n; i++) 96 { 97 if (visited[i] == 0) return false; 98 } 99 100 return true; 101 } 102 } 103 104 // dfs 105 public class Solution2 { 106 public bool ValidTree(int n, int[,] edges) { 107 var adjacentList = new IList<int>[n]; 108 109 for (int i = 0; i < edges.GetLength(0); i++) 110 { 111 if (adjacentList[edges[i, 0]] == null) 112 { 113 adjacentList[edges[i, 0]] = new List<int>(); 114 } 115 116 adjacentList[edges[i, 0]].Add(edges[i, 1]); 117 118 if (adjacentList[edges[i, 1]] == null) 119 { 120 adjacentList[edges[i, 1]] = new List<int>(); 121 } 122 123 adjacentList[edges[i, 1]].Add(edges[i, 0]); 124 } 125 126 var visited = new bool[n]; 127 128 if (HasCycle(adjacentList, 0, -1, visited)) 129 { 130 return false; 131 } 132 133 for (int i = 0; i < n; i++) 134 { 135 if (!visited[i]) return false; 136 } 137 138 return true; 139 } 140 141 private bool HasCycle(IList<int>[] adjacentList, int cur, int prev, bool[] visited) 142 { 143 if (visited[cur]) return true; 144 visited[cur] = true; 145 146 if (adjacentList[cur] != null) 147 { 148 foreach (var e in adjacentList[cur]) 149 { 150 // since this is undirected graph, we add edges twice so we don't want to traverse one edge more than once 151 if (e != prev) 152 { 153 if (visited[e] || HasCycle(adjacentList, e, cur, visited)) 154 { 155 return true; 156 } 157 } 158 } 159 } 160 161 return false; 162 } 163 }
1 public class Solution { 2 public bool ValidTree(int n, int[,] edges) { 3 var adjacentList = new IList<int>[n]; 4 5 // we need to add the edges twice as the graph is undirected and if we don't add twice, we won't be able traverse it. 6 // But when we do BFS/DFS, we need to make sure to traverse the same edge more than once 7 for (int i = 0; i < edges.GetLength(0); i++) 8 { 9 if (adjacentList[edges[i, 0]] == null) 10 { 11 adjacentList[edges[i, 0]] = new List<int>(); 12 } 13 14 adjacentList[edges[i, 0]].Add(edges[i, 1]); 15 16 if (adjacentList[edges[i, 1]] == null) 17 { 18 adjacentList[edges[i, 1]] = new List<int>(); 19 } 20 21 adjacentList[edges[i, 1]].Add(edges[i, 0]); 22 } 23 24 var visited = new int[n]; 25 var queue = new Queue<int>(); 26 queue.Enqueue(0); 27 28 // there are three states of visited, 0 means not visited, 1 means visiting, 2 means visited 29 visited[0] = 1; 30 31 while (queue.Count > 0) 32 { 33 var cur = queue.Dequeue(); 34 35 if (adjacentList[cur] != null) 36 { 37 foreach (var c in adjacentList[cur]) 38 { 39 if (visited[c] == 1) return false; 40 if (visited[c] == 0) 41 { 42 visited[c] = 1; 43 queue.Enqueue(c); 44 } 45 } 46 } 47 48 visited[cur] = 2; 49 } 50 51 for (int i = 0; i < n; i++) 52 { 53 if (visited[i] == 0) return false; 54 } 55 56 return true; 57 } 58 59 private bool HasCycle(IList<int>[] adjacentList, int cur, int prev, bool[] visited) 60 { 61 if (visited[cur]) return true; 62 visited[cur] = true; 63 64 if (adjacentList[cur] != null) 65 { 66 foreach (var e in adjacentList[cur]) 67 { 68 // since this is undirected graph, we add edges twice so we don't want to traverse one edge more than once 69 if (e != prev) 70 { 71 if (visited[e] || HasCycle(adjacentList, e, cur, visited)) 72 { 73 return true; 74 } 75 } 76 } 77 } 78 79 return false; 80 } 81 } 82 83 // dfs 84 public class Solution1 { 85 public bool ValidTree(int n, int[,] edges) { 86 var adjacentList = new IList<int>[n]; 87 88 for (int i = 0; i < edges.GetLength(0); i++) 89 { 90 if (adjacentList[edges[i, 0]] == null) 91 { 92 adjacentList[edges[i, 0]] = new List<int>(); 93 } 94 95 adjacentList[edges[i, 0]].Add(edges[i, 1]); 96 97 if (adjacentList[edges[i, 1]] == null) 98 { 99 adjacentList[edges[i, 1]] = new List<int>(); 100 } 101 102 adjacentList[edges[i, 1]].Add(edges[i, 0]); 103 } 104 105 var visited = new bool[n]; 106 107 if (HasCycle(adjacentList, 0, -1, visited)) 108 { 109 return false; 110 } 111 112 for (int i = 0; i < n; i++) 113 { 114 if (!visited[i]) return false; 115 } 116 117 return true; 118 } 119 120 private bool HasCycle(IList<int>[] adjacentList, int cur, int prev, bool[] visited) 121 { 122 if (visited[cur]) return true; 123 visited[cur] = true; 124 125 if (adjacentList[cur] != null) 126 { 127 foreach (var e in adjacentList[cur]) 128 { 129 // since this is undirected graph, we add edges twice so we don't want to traverse one edge more than once 130 if (e != prev) 131 { 132 if (visited[e] || HasCycle(adjacentList, e, cur, visited)) 133 { 134 return true; 135 } 136 } 137 } 138 } 139 140 return false; 141 } 142 }