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 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 }