深度优先搜索
Posted 浮云神码
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了深度优先搜索相关的知识,希望对你有一定的参考价值。
本次分享涉及图的连通分量,计算连通分量可以通过广度优先搜索和深度优先搜索实现。
下面通过两种方式来实现,第一种是通过显示的栈来实现深度优先搜索,第二种是通过递归来实现深度优先搜索。
本题的图是通过邻接矩阵来表示的。
import java.util.Stack;
/**
* https://leetcode-cn.com/problems/number-of-provinces
* 547. 省份数量
* 难度 中等
* 有 n 个城市,其中一些彼此相连,另一些没有相连。如果城市 a 与城市 b 直接相连,
* 且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。
*
* 省份 是一组直接或间接相连的城市,组内不含其他没有相连的城市。
*
* 给你一个 n x n 的矩阵 isConnected ,其中 isConnected[i][j] = 1
* 表示第 i 个城市和第 j 个城市直接相连,而 isConnected[i][j] = 0 表示二者不直接相连。
*
* 返回矩阵中 省份 的数量。
*
* 示例 1:
* 输入:isConnected = [[1,1,0],[1,1,0],[0,0,1]]
* 输出:2
* 示例 2:
* 输入:isConnected = [[1,0,0],[0,1,0],[0,0,1]]
* 输出:3
*
* 提示:
*
* 1 <= n <= 200
* n == isConnected.length
* n == isConnected[i].length
* isConnected[i][j] 为 1 或 0
* isConnected[i][i] == 1
* isConnected[i][j] == isConnected[j][i]
*
* 来源:力扣(LeetCode)
* 链接:https://leetcode-cn.com/problems/number-of-provinces
*/
public class NumberOfProvinces {
public int findCircleNum(int[][] isConnected) {
int n = isConnected.length;
// 顶点数为n, 创建长度为n的boolean数组存储是否已访问过对应的顶点
boolean[] visited = new boolean[n];
Stack<Integer> stack = new Stack<>();
int result = 0;
for (int i = 0; i < n; i++) {
// 若顶点未访问过, 则通过isConnected找到该顶点所有连通的顶点
// 将他们标记为已访问
if (!visited[i]) {
visited[i] = true;
result++;
// 这里将该顶点所有的邻接顶点入栈
for (int j = 0; j < n; j++) {
if (!visited[j] && isConnected[i][j] == 1) {
visited[j] = true;
stack.push(j);
}
}
// 这里通过栈使用深度优先搜索, 不断的将邻接点入栈处理
while (!stack.isEmpty()) {
Integer current = stack.pop();
for (int j = 0; j < n; j++) {
if (!visited[j] && isConnected[current][j] == 1) {
visited[j] = true;
stack.push(j);
}
}
}
}
}
return result;
}
/**
* 递归版本
* @param isConnected
* @return
*/
public int findCircleNum2(int[][] isConnected) {
int n = isConnected.length;
int result = 0;
boolean[] visited = new boolean[n];
// 依次遍历所有顶点
for (int i = 0; i < n; i++) {
// 一旦遇到未遍历过的顶点, 就意味着存在一个连通分量
if (!visited[i]) {
// 之前没有被搜索到过, 连通分量+1
result++;
visited[i] = true;
// 这里进行递归调用
dfs(isConnected, visited, i);
}
}
return result;
}
public void dfs(int[][] isConnected, boolean[] visited, int current) {
int n = isConnected.length;
for (int i = 0; i < n; i++) {
if (isConnected[current][i] == 1 && !visited[i]) {
visited[i] = true;
// 不断进行递归调用, 直到整个连通分量的所有顶点全部标记
dfs(isConnected, visited, i);
}
}
}
}
以上是关于深度优先搜索的主要内容,如果未能解决你的问题,请参考以下文章