判断图中是否有环
判断图中是否有环
1. 有向图【BFS】
207. 课程表
用例:
[[1,4],[2,4],[3,1],[3,2]]
弹出1的时候,4的入度由 2 变成 1
当再弹出2的时候,4的入度由 1 变成0,此时可以入队!!!
class Solution {
Deque<Integer> deque = new ArrayDeque<>();
Map<Integer, List<Integer>> map = new HashMap<>();
int[] inNum;
int count = 0; // 入度为0 的个数
public boolean canFinish(int numCourses, int[][] prerequisites) {
Set<Integer> set = new HashSet<>();
for (int[] prerequisite : prerequisites) {
int start = prerequisite[0];
int end = prerequisite[1];
set.add(start);
set.add(end);
List<Integer> orDefault = map.getOrDefault(start, new ArrayList<>());
orDefault.add(end);
map.put(start, orDefault); // 1. 邻接表
}
inNum = new int[numCourses];
for (int[] prerequisite : prerequisites) {
inNum[prerequisite[1]]++; // 2. 计算入度
}
for (int i = 0; i < inNum.length; i++) {
if (inNum[i] == 0 && map.containsKey(i)){ // 邻接表中入度为 0 的入队
deque.offer(i);
}
}
bfs();
return count == set.size(); // 入度为 0 的个数 == 节点的个数
}
public void bfs(){
while (!deque.isEmpty()){
int len = deque.size();
while (len > 0){
Integer peek = deque.poll();
count++;
List<Integer> list = map.getOrDefault(peek, new ArrayList<>());
for (Integer integer : list) {
inNum[integer]--;
if (inNum[integer] == 0){
deque.offer(integer);
}
}
len--;
}
}
}
}
2. 无向图【并查集 union find】
547. 省份数量
class Solution {
int[] arr;
int size;
public int findCircleNum(int[][] isConnected) {
int n = isConnected.length;
size = n;
arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = i;
}
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) { // 只考虑上半三角即可!!!
if (isConnected[i][j] == 1){
union(i, j);
}
}
}
return size;
}
public int find(int x){
if (x == arr[x]){
return x;
}
return find(arr[x]);
}
public void union(int i, int j){
int f1 = find(i);
int f2 = find(j);
if (f1 != f2){
size--; // 能连 ===> 干掉一个省份!!!
arr[f2] = f1;
}
}
}