王清欢Randy 王清欢Randy
首页
  • 编程语言

    • C/C++ 学习笔记
    • Golang 学习笔记
  • 算法分析

    • LeetCode 刷题笔记
  • 操作系统

    • Linux 基础
    • Vim 实用技巧
    • Shell 脚本编程
    • GDB 学习笔记
  • 开发工具

    • Git 学习笔记
  • 分布式理论

    • 共识算法
    • 分布式事务
  • 数据库内核

    • PostgreSQL
    • Postgres-XL
  • hidb
  • pgproxy
  • 实用技巧
  • 学习方法
  • 资源分享
GitHub (opens new window)
首页
  • 编程语言

    • C/C++ 学习笔记
    • Golang 学习笔记
  • 算法分析

    • LeetCode 刷题笔记
  • 操作系统

    • Linux 基础
    • Vim 实用技巧
    • Shell 脚本编程
    • GDB 学习笔记
  • 开发工具

    • Git 学习笔记
  • 分布式理论

    • 共识算法
    • 分布式事务
  • 数据库内核

    • PostgreSQL
    • Postgres-XL
  • hidb
  • pgproxy
  • 实用技巧
  • 学习方法
  • 资源分享
GitHub (opens new window)
  • 基础算法

    • 双指针

      • 双指针基础
      • 碰撞指针
      • 快慢指针
      • 滑动窗口
    • 二分查找

      • 基础应用
      • 边界收缩
      • 局部有序
    • 排序算法

      • 01八大排序
      • 02快速排序
      • 03归并排序
      • 04桶排序
      • 05堆排序
    • 优先搜索

      • 01递归
      • 02网格结构深度优先搜索
      • 03树结构深度优先搜索
      • 04图结构深度优先搜索
        • 02 图结构深度优先搜索
          • 深度优先搜索简介
          • 547 省份数量
      • 05网格结构广度优先搜索
      • 06树结构广度优先搜索
      • 07图结构广度优先搜索
    • 回溯算法

      • 01递归
      • 02 子集问题
      • 03 全排列问题
      • 04 组合问题
      • 05 回溯搜索问题
  • 基础数据结构

    • 线性表与哈希表

      • 01数组
      • 02栈和队列
      • 03单调栈
      • 04优先队列
      • 05双端队列
      • 06哈希表
      • 07多重集合
      • 08前缀和
      • 09数据结构设计
    • 字符串

      • 01字符串比较
      • 02回文字符串
      • 03字符串匹配
      • 04字符串算术表达式
    • 单链表

      • 01链表基础操作
      • 02链表遍历
    • 二叉树

      • 01二叉树的属性
      • 02二叉树的操作
      • 03层次遍历
      • 04前中后序遍历
      • 05二叉搜索树的属性
      • 06二叉搜索树的操作
      • 07字典树
      • 08二叉搜索树BST
    • 图

      • 01二分图
      • 02拓扑排序
      • 03并查集
      • 04最小生成树
      • 05最短路径
  • 进阶算法

    • 贪心算法

      • 01跳跃游戏
      • 02分配问题
      • 03区间问题
    • 分治策略

    • 动态规划

      • 01一维动态规划
      • 02二维动态规划
      • 03分割型动态规划
      • 04子序列问题
      • 05背包问题
      • 06字符串编辑问题
      • 07股票交易问题
  • 其他内容

    • 数学问题

      • 01公倍数与公因数
      • 02质数问题
      • 03进制转换问题
      • 04数字字符串求和问题
      • 05众数问题
      • 06中位数问题
      • 07数字处理问题
      • 08随机数问题
    • 位运算

      • 01位运算基础
      • 02妙用异或运算
      • 03二进制特性
  • LeetCode刷题笔记
  • 基础算法
  • 优先搜索
王清欢
2023-03-24
目录

04图结构深度优先搜索

# 02 图结构深度优先搜索

# 深度优先搜索简介

​ 深度优先搜索(depth-first seach,DFS)在搜索到一个新的节点时,立即对该新节点进行遍历;因此遍历需要用先入后出的栈来实现,也可以通过与栈等价的递归来实现。

​ 对于树结构而言,由于总是对新节点调用遍历,因此看起来是向着 深 的方向前进,或者说是垂直方向。考虑如下一颗简单的树,由4 个节点构成共三层,其 DFS 过程如下图所示:

dfsgraph

​ 图通常有两种表示方法。假设图中一共有 n 个节点、m 条边。

​ 第一种表示方法是邻接矩阵(adjacency matrix):我们可以建立一个 n × n 的矩阵 G,如果第 i 个节点连向第 j 个节点,则 G[i][j]= 1,反之为 0;如果图是无向的,则这个矩阵一定是对称矩阵,即 G[i][j] = G[j][i]。

​ 第二种表示方法是邻接链表(adjacency list):我们可以建立一个大小为 n 的数组,每个位置 i 储存一个数组 或者链表,表示第 i 个节点连向的其它节点。

​ 邻接矩阵空间开销比邻接链表大,但是邻接链表不支持快速查找 i 和 j 是否相连,因此两种表示方法可以根据题目需要适当选择。除此之外,我们也可以直接用一个 m × 2 的矩阵储存所有的边。

# 547 省份数量 (opens new window)

​ 给定一个二维的 0-1 矩阵,如果第 (i, j) 位置是 1,则表示第 i 城市和第 j 城市相连。已知连接关系是可以传递的,即如果城市 a 与城市 b 直接相连,且城市 b 与城市 c 直接相连,那么城市 a 与城市 c 间接相连。一组直接或间接相连的城市通同属于一个省份。求一共有多少个省份。

​ 输入是一个二维数组,输出是一个整数,表示省份数量。因为城市连接关系具有对称性,该二维数组为对称矩阵。同时,因为自己与自己相连,对角线上的值全部为 1。

graph1

输入:isConnected = [[1,1,0],[1,1,0],[0,0,1]]
输出:2

解析:

​ 本题和200 岛屿数量 (opens new window)题本质上是同一道题。

​ 对于题目 200,二维矩阵也是一种图,其表示方法是:每个位置代表一个节点,每个节点与上下左右四个节点相邻。而在本题里面,则是图的邻接矩阵表示:每一行(列)表示一个节点,它的每列(行)表示是否存在一个相邻节点。

​ 因此题目 200 拥有 m × n 个节点,每个节点有 4 条边;而本题拥有 n 个节点,每个节点最多有 n 条边,表示和所有城市都相连,最少可以有 1 条边,表示自己与自己相连。所以这道题与题目 200 本质上是同一道题:搜索图中省份数量和搜索二维矩阵中的岛屿数量。

​ 所以我们仍然使用一个主函数和一个辅函数配合解决本题,主函数用于遍历所有的搜索位置,判断是否满足开始搜索的条件,如果可以即在辅函数中进行搜索。与二维数组情况不同的是,在主函数中我们要设置一个数组用于记录节点(城市)是否已经被访问过;辅函数中我们不再仅仅四向遍历而是要搜索所有与当前节点相连的节点,并递归搜索所有相连的点。

class Solution {
public:
    void dfs(vector<vector<int>>& isConnected, int i, vector<bool>& visited){
        if(visited[i]) return;
        visited[i] = true;
        for(int j=0;j<visited.size();++j){
            if(isConnected[i][j]==1 && !visited[j]){
                dfs(isConnected,j,visited);
            }
        }
    }

    int findCircleNum(vector<vector<int>>& isConnected) {
        if(isConnected.empty() || isConnected[0].empty()){
            return 0;
        }
        vector<bool> visited(isConnected.size(),false);
        int ans = 0;
        for(int i=0;i<visited.size();++i){
            if(!visited[i]){
                dfs(isConnected,i,visited);
                ++ans;
            }
        }
        return ans;
    }
};
上次更新: 2023/11/19, 12:55:48
03树结构深度优先搜索
05网格结构广度优先搜索

← 03树结构深度优先搜索 05网格结构广度优先搜索→

Theme by Vdoing | Copyright © 2023-2024 Wang Qinghuan | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式