Graph Valid Tree
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.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. // 方法1,对每个V BFS,结束之后看是否已经完成所有V
class Solution {
public boolean validTree(int n, int[][] edges) {
if (edges == null || edges.length != n - 1) return false;
List<Set<Integer>> graph = initGraph(n, edges);
// bfs, 以 0 为入口
Deque<Integer> queue = new LinkedList<>();
Set<Integer> visited = new HashSet<>();
queue.addFirst(0);
visited.add(0);
while (! queue.isEmpty()) {
int v = queue.removeLast();
for (int neighbor : graph.get(v)) {
if (visited.contains(neighbor)) continue;
visited.add(neighbor);
queue.addFirst(neighbor);
}
}
return visited.size() == n;
}
private List<Set<Integer>> initGraph(int n, int[][] edges) {
List<Set<Integer>> graph = new ArrayList<>();
for (int i = 0; i < n; ++i) {
graph.add(new HashSet<Integer>());
}
for (int i = 0; i < edges.length; ++i) {
int u = edges[i][0];
int v = edges[i][1];
graph.get(u).add(v);
graph.get(v).add(u);
}
return graph;
}
} class Solution:
# @param {int} n an integer
# @param {int[][]} edges a list of undirected edges
# @return {boolean} true if it's a valid tree, or false
def validTree(self, n, edges):
# 先把edges list的形式转化成adjacent list的形式,即{node:neighbors}
def init_graph(n, edges):
graph = collections.defaultdict(set)
for edge in edges:
u = edge[0]
v = edge[1]
graph[u].add(v)
graph[v].add(u)
return graph
# 先生成adj list格式的graph,然后用bfs判断是否连通
if n != len(edges) + 1: return False
if n == 1: return True
graph = init_graph(n, edges)
queue = collections.deque()
visited = set()
queue.appendleft(0)
visited.add(0)
while queue:
node = queue.pop()
for neighbor in graph[node]:
if neighbor in visited:
continue
queue.appendleft(neighbor)
visited.add(neighbor)
return len(visited) == n // 方法2,传说中的 Union Find Algorithm
class Solution {
private int[] ids;
private int[] rank;
private int count;
private void makeSet(int size) {
ids = new int[size];
rank = new int[size];
count = size;
// initialize union set data structure
Arrays.fill(rank, 0);
for (int i = 0; i < size; ++i) ids[i] = i;
}
private int find(int x) {
while (ids[x] != x) {
ids[x] = find(ids[x]);
x = ids[x];
}
return x;
}
private void union(int x, int y) {
int rootx = find(x);
int rooty = find(y);
if (rootx == rooty) return;
if (rank[rootx] < rank[rooty]) {
ids[rootx] = rooty;
} else if (rank[rootx] > rank[rooty]) {
ids[rooty] = rootx;
} else {
ids[rootx] = rooty;
rank[rooty]++;
}
count--;
}
public boolean validTree(int n, int[][] edges) {
if (edges == null || edges.length != n - 1) return false;
makeSet(n);
for (int[] edge : edges) {
int u = edge[0], v = edge[1];
union(u, v);
}
return count == 1;
}
} class Solution {
vector<int> ids;
vector<int> ranks;
int count;
void makeSet(int size) {
ids.resize(size);
ranks.resize(size);
count = size;
for (int i = 0; i < size; ++i) {
ids[i] = i;
}
}
int find(int id) {
if (ids[id] == id) return id;
while (ids[id] != id) {
id = ids[id];
}
return id;
}
void _union(int x, int y) {
int rootx = find(x);
int rooty = find(y);
if (rootx == rooty) return;
if (ranks[rootx] < ranks[rooty]) ids[rootx] = rooty;
else if (ranks[rootx] > ranks[rooty]) ids[rooty] = rootx;
else {
ids[rootx] = rooty;
ranks[rooty]++;
}
count--;
}
public:
bool validTree(int n, vector<pair<int, int>>& edges) {
if (edges.size() != n - 1) return false;
makeSet(n);
for (auto& _pair : edges) {
_union(_pair.first, _pair.second);
}
return count == 1;
}
};