图的表示
图的比较方便的表示方法有两种,第一种是matrix(比如有number of island这种),第二种是邻接矩阵的形式。
如果题目中给了边的信息,最好转化成邻接矩阵。
DFS
void dfs(graph, visited, current){
if (visited[current]) return;
visited[current] = true; // Need to set this line first
for (auto neighbor:graph[current]){
if(!visited[neighbor]) {
dfs(graph,visited, neighbor);
}
}
}
BFS
并查集
在判断联通情况的时候可以和dfs/bfs互换,union find优点是可以方便处理动态图,缺点是并不是O(1)time,而bfs/dfs相反。
在面试的时候可以写两个并查集版本,一个是简易版本,一个是完整带weighted quick-union and path compression的版本。
class UF { // 完整版本
// union-find, bfs
int N;
int[] id;
int[] sz;
int segments;
public UF(int n){
N = n;
segments = n;
id = new int[N];
sz = new int[N];
for(int i=0; i<N; i++){
id[i] = i;
sz[i] = 1;
}
}
public int root(int i) {
while(i!=id[i]){
id[i] = id[id[i]]; // path compression
i = id[i];
}
return i;
}
public void connect(int p, int q){
int i = root(p);
int j = root(q);
if(i == j) return;
if(sz[i]<sz[j]) { // if-else: weighted quick-union
id[i] = j;
sz[j] += sz[i];
}
else if(sz[i]>sz[j]) {
id[j] = i;
sz[i] += sz[j];
}
else {
id[j] = i;
sz[i] += sz[j];
}
segments--;
}
public boolean connected(int p, int q) {
if(root(p)==root(q)){
return true;
}
return false;
}
}
简单版本 (LC261代码)
public class Solution {
public boolean validTree(int n, int[][] edges) {
// initialize n isolated islands
int[] nums = new int[n];
Arrays.fill(nums, -1);
// perform union find
for (int i = 0; i < edges.length; i++) {
int x = find(nums, edges[i][0]);
int y = find(nums, edges[i][1]);
// if two vertices happen to be in the same set
// then there's a cycle
if (x == y) return false;
// union
nums[x] = y;
}
return edges.length == n - 1;
}
int find(int nums[], int i) {
if (nums[i] == -1) return i;
return find(nums, nums[i]);
}
}