总结
- 无论哪种方法在标记之前一定要有判断标记的操作,这样会防止死循环现象,无论你是否理解这都是一个保险的操作
- 对于图的遍历有几个要素:一定有一个visited数组来进行标记。
- dfs经典递归,bfs经典队列,在一些模拟题当中还可以使用直接遍历的方式两层for循环
- 对于并查集还需要判断层高才能够按规则合并,因此还要有一个level数组。
- level的增加情况只有在两个要合并的树是相同的层高才会出现加一,因为我们已经约定了低层高的树要并入高层树,这样层高是不会改变的。
dfs方法
static int getProvince(int[][] cities){
boolean[] visited = new boolean[cities.length];
int count = 0;
for(int i = 0 ; i < visited.length ; i++ ){
if(visited[i] != true){
dfs(cities , i , visited);
count++;
}
}
return count;
}
private static void dfs(int[][] cities , int index , boolean[] visited) {
for(int i = index ; i < cities.length ; i++){
for( int j = i+1 ; j < cities.length ; j++){
if(cities[i][j] == 1 && !visited[j]){
visited[j] = true;
dfs(cities , j , visited);
}
}
}
}
bfs方法
bfs的经典思想就是队列
private static int bfs(int[][] cities ){
Queue<Integer> queue = new LinkedList<>();
boolean[] visited = new boolean[cities.length];
int count = 0;
for(int i = 0 ; i < cities.length ; i++){
if(!visited[i]){
queue.offer(i);
visited[i] = true;
while(!queue.isEmpty()){
int tmp = queue.poll();
for(int j1 = 0 ; j1 < cities.length ; j1++){
if(cities[tmp][j1] == 1 && !visited[j1]){//visited很重要,否则会出现死循环一直入队的现象
visited[j1] = true;//可以记为:在标记之前一定有判断是否已经标记的操作
queue.offer(j1);
}
}
}
count++;
}
}
return count;
}