Graph Valid Tree
Problem Statement
You’re a graph botanist verifying if an undirected graph with n nodes and edges forms a tree—no cycles, fully connected. Return true if it’s a valid tree. This medium-level DFS/Union-Find challenge is a structural study—prune those loops!
Example
Input: n = 5, edges = [[0,1],[0,2],[0,3],[1,4]]
Graph:
0 /|\ 1 2 3 | 4
Output: true (Tree: n-1 edges, no cycle)
Input: n = 5, edges = [[0,1],[1,2],[2,3],[1,3],[1,4]]
Output: false (Cycle: 1-2-3-1)
Code
Java
Python
JavaScript
class Solution {
public boolean validTree(int n, int[][] edges) {
if (edges.length != n - 1) return false;
List> graph = new ArrayList<>();
for (int i = 0; i < n; i++) graph.add(new ArrayList<>());
for (int[] edge : edges) {
graph.get(edge[0]).add(edge[1]);
graph.get(edge[1]).add(edge[0]);
}
boolean[] visited = new boolean[n];
dfs(graph, 0, -1, visited);
for (boolean v : visited) if (!v) return false; // Check connectivity
return true;
}
private boolean dfs(List> graph, int node, int parent, boolean[] visited) {
visited[node] = true;
for (int neighbor : graph.get(node)) {
if (!visited[neighbor]) {
if (!dfs(graph, neighbor, node, visited)) return false;
} else if (neighbor != parent) {
return false; // Cycle
}
}
return true;
}
}
from collections import defaultdict
def valid_tree(n, edges):
if len(edges) != n - 1:
return False
graph = defaultdict(list)
for u, v in edges:
graph[u].append(v)
graph[v].append(u)
visited = [False] * n
def dfs(node, parent):
visited[node] = True
for neighbor in graph[node]:
if not visited[neighbor]:
dfs(neighbor, node)
elif neighbor != parent:
return False
return True
dfs(0, -1)
return all(visited) # Ensure fully connected
function validTree(n, edges) {
if (edges.length !== n - 1) return false;
let graph = Array(n).fill().map(() => []);
for (let [u, v] of edges) {
graph[u].push(v);
graph[v].push(u);
}
let visited = new Array(n).fill(false);
function dfs(node, parent) {
visited[node] = true;
for (let neighbor of graph[node]) {
if (!visited[neighbor]) {
dfs(neighbor, node);
} else if (neighbor !== parent) {
return false;
}
}
return true;
}
dfs(0, -1);
return visited.every(v => v);
}
Explanation
- Tree Insight: n-1 edges + no cycles + connected = tree.
- Flow: Check edge count, DFS for cycles, verify all nodes visited.
- Example Walkthrough: [0,1],[1,2],[2,0] → n-1 fails, cycle detected → false.
- Union-Find Alt: Merge edges, check for cycles and single component.
- Key Check: Edge count shortcut eliminates non-trees early.
Note
Time complexity: O(V + E), Space complexity: O(V + E). A tree-validating treasure—pristine and precise!
