深度优先搜索(dfs)--矩阵部分-leetcode以及常见题

news2025/1/15 6:24:23

介绍

深度优先搜索(Depth-First Search,DFS)是一种常用的图搜索算法,它用于查找图或树数据结构中的路径或解决问题。下面是深度优先搜索的常见步骤以及一个示例问题:

深度优先搜索的常见步骤:

  1. 选择起始节点:首先,选择一个起始节点,从该节点开始搜索。

  2. 访问节点:访问当前节点,并标记它为已访问。这可以通过将节点标记为已访问或将其添加到访问过的节点列表中来实现。

  3. 探索相邻节点:从当前节点出发,探索其相邻节点。这可以通过遍历与当前节点相连接的边或邻接节点来实现。

  4. 递归或栈:对于每个相邻节点,如果它还没有被访问过,就递归地或使用栈将其作为当前节点进行访问。这是深度优先搜索的关键部分,它会一直沿着一个路径深入,直到达到叶子节点或无法继续深入为止。

  5. 回溯:当无法继续深入时,回溯到上一个节点,并尝试探索其他相邻节点,直到找到解决方案或访问完所有节点。

  6. 重复步骤3至步骤5:重复步骤3至步骤5,直到找到问题的解决方案或访问了所有可达节点。

简单的例子

        

#include <iostream>
#include <vector>

using namespace std;

// 定义图的节点结构
struct Node {
    int val;
    vector<Node*> neighbors;
    bool visited;

    Node(int _val) : val(_val), visited(false) {}
};

// 深度优先搜索函数
bool dfs(Node* current, Node* target, vector<Node*>& path) {
    if (current == target) {
        path.push_back(current);
        return true;
    }

    current->visited = true;
    path.push_back(current);

    for (Node* neighbor : current->neighbors) {
        if (!neighbor->visited) {
            if (dfs(neighbor, target, path)) {
                return true;
            }
        }
    }

    // 如果无法找到路径,回溯
    path.pop_back();
    return false;
}

int main() {
    // 创建节点
    Node* A = new Node(1);
    Node* B = new Node(2);
    Node* C = new Node(3);
    Node* D = new Node(4);

    // 构建图的连接关系
    A->neighbors.push_back(B);
    A->neighbors.push_back(C);
    B->neighbors.push_back(D);
    C->neighbors.push_back(D);

    // 初始化路径
    vector<Node*> path;

    // 执行深度优先搜索
    bool foundPath = dfs(A, D, path);

    // 输出结果
    if (foundPath) {
        cout << "Path from A to D found:" << endl;
        for (Node* node : path) {
            cout << node->val << " ";
        }
        cout << endl;
    } else {
        cout << "Path from A to D not found." << endl;
    }

    // 释放节点内存
    delete A;
    delete B;
    delete C;
    delete D;

    return 0;
}
/*
在这个示例中,我们首先定义了一个表示图节点的结构体Node,每个节点具有一个值、一个标记用于表示是否已访问和一个邻接节点的列表。然后,我们实现了一个深度优先搜索函数dfs,该函数递归地探索图中的节点,同时维护一个路径列表。如果找到从起始节点到目标节点的路径,它将返回true,并在路径列表中存储找到的路径。

在main函数中,我们创建了图的节点并构建了节点之间的连接关系。然后,我们调用dfs函数来查找从节点A到节点D的路径,并输出结果。如果路径存在,它将打印出路径上的节点值,否则会显示未找到路径。最后,我们释放了节点的内存以避免内存泄漏。
*/

题目1:华为机试题43 迷宫问题。

地址 迷宫问题_牛客题霸_牛客网

题目描述:

定义一个二维数组 N*M ,如 5 × 5 数组下所示:

int maze[5][5] = {
0, 1, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 0, 0,
0, 1, 1, 1, 0,
0, 0, 0, 1, 0,
};

        

它表示一个迷宫,其中的1表示墙壁,0表示可以走的路,只能横着走或竖着走,不能斜着走,要求编程序找出从左上角到右下角的路线。入口点为[0,0],既第一格是可以走的路。

数据范围:

2≤n,m≤10  , 输入的内容只包含

0≤val≤1

输入描述:

输入两个整数,分别表示二维数组的行数,列数。再输入相应的数组,其中的1表示墙壁,0表示可以走的路。数据保证有唯一解,不考虑有多解的情况,即迷宫只有一条通道。

输入:

5 5

0 1 0 0 0

0 1 1 1 0

0 0 0 0 0

0 1 1 1 0

0 0 0 1 0

复制

输出:

(0,0)

(1,0)

(2,0)

(2,1)

(2,2)

(2,3)

(2,4)

(3,4)

(4,4)

复制

示例2

输入:

5 5

0 1 0 0 0

0 1 0 1 0

0 0 0 0 1

0 1 1 1 0

0 0 0 0 0

复制

输出:

(0,0)

(1,0)

(2,0)

(3,0)

(4,0)

(4,1)

(4,2)

(4,3)

(4,4)

复制

说明:

注意:不能斜着走!!


#include <iostream>
#include<vector>
using namespace std;

vector<vector<int> > res;
bool dfs(vector<vector<int>>& v, int m, int n, int i, int j) {

    if (i == m - 1 && j == n - 1) {
        res.push_back({i, j});
        return true;
    }

    //通过这个false 判定这个结果。

    if (i < 0 || i >= m || j < 0 || j >= n || v[i][j] == -1 || v[i][j] == 1) {
        return false;
    }

    v[i][j] = -1;
    res.push_back({i, j});

    if (dfs(v, m, n, i - 1, j) || dfs(v, m, n, i + 1, j) ||
            dfs(v, m, n, i, j - 1) || dfs(v, m, n, i, j + 1)) {
        return true;
    }

    res.pop_back();
    v[i][j] = 0;

    return false;

}

int main() {

    int m, n;
    int temp;
    cin >> m >> n;
    vector<vector<int> > v(m, vector<int>(n, 0));

    for (int i = 0; i < m; i++) {
        for (int j = 0; j < n; j++) {

            cin >> v[i][j];
        }
    }

    dfs(v,m,n,0,0);

    for(const auto & x:res){
        // printf("(%d,%d)\n",x[0],[1]);
        // printf("(%d,%d) \n",x[0],[1]);
        printf("(%d,%d)\n", x[0], x[1]);
    }

    return 0;

}

题目2:剑指offer12 矩阵中的路径

链接:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台

给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。

单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。

例如,在下面的 3×4 的矩阵中包含单词 "ABCCED"(单词中的字母已标出)。

 

示例 1:

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"
输出:true

示例 2:

输入:board = [["a","b"],["c","d"]], word = "abcd"
输出:false
class Solution6 {
public:
       bool dfs(vector<vector<char>>& board,string word,int i,int j,int k,vector<vector<int>> &path){

        if(i<0||i>=board.size()||j<0||j>=board[0].size()||path[i][j]==1){
            return false;
        }

          if(board[i][j]==word[k]&&k==word.size()-1){
            return true;
        }

        if(word[k]==board[i][j]){

            path[i][j]=1;
            if(dfs(board,word,i+1,j,k+1,path)||dfs(board,word,i-1,j,k+1,path)||dfs(board,word,i,j-1,k+1,path)||dfs(board,word,i,j+1,k+1,path)){
                 return true;
        }

        }

        path[i][j]=0;
        return false;

    }

    bool exist(vector<vector<char>>& board, string word) {

        int m=board.size();
        int n=board[0].size();
        bool res=false;
        vector<vector<int> > path(m,vector<int>(n,0));
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){

                res = dfs(board, word, i, j, 0, path);
                if(res){
                    //i,j 是起点只要有一个七点满足条件就可以
                    return true;
                }

            }
        }

        return  res;
    }

};

int main()
{

    Solution6 s;
    vector<vector<char>> board = {{'A', 'B', 'C', 'E'}, {'S', 'F', 'C', 'S'}, {'A', 'D', 'E', 'E'}};
    // vector< vector<char> > board={}
    string word = "ABCCED";

    bool res = s.exist(board, word);
    cout << res << endl;

    system("pause");
    return 0;
}

题目3 leetcode 200岛屿的数量 

leet200 岛屿的数量 https://leetcode.cn/problems/number-of-islands/

给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。

岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。

此外,你可以假设该网格的四条边均被水包围。

示例 1:

输入:grid = [

  ["1","1","1","1","0"],

  ["1","1","0","1","0"],

  ["1","1","0","0","0"],

  ["0","0","0","0","0"]

]

输出:1

示例 2:

输入:grid = [

  ["1","1","0","0","0"],

  ["1","1","0","0","0"],

  ["0","0","1","0","0"],

  ["0","0","0","1","1"]

]

//可以这么理解,(遍历整个岛屿的元素,如果是1就对这个点的值进行深度优先搜索,将相邻的全部改成0) 岛屿的数量+1。

class Solution7
{
public:
    int n;
    void dfs(vector<vector<char>> &grid, int i, int j, int m, int n)
    {

        if (i < 0 || i >= m || j < 0 || j >= n || grid[i][j] == '0')
        {
            return;
        }

        grid[i][j] = '0';
        dfs(grid, i - 1, j, m, n);
        dfs(grid, i + 1, j, m, n);
        dfs(grid, i, j - 1, m, n);
        dfs(grid, i, j + 1, m, n);

        return;
    }

    int numIslands(vector<vector<char>> &grid)
    {

        int m = grid.size();
        int n = grid[0].size();

        int num = 0;
        // vector<vector<bool> > path=vector(m,vector<int>(n,0));

        for (int i = 0; i < m; i++)
        {

            for (int j = 0; j < n; j++)
            {

                if (grid[i][j] == '1')
                {
                    n++;
                    dfs(grid, i, j, m, n);
                }
            }
        }

        return n;
    }
};

int main()
{

    Solution7 s7;

    vector<vector<char>> gird = {{'1'}, {'1'}};

    auto res = s7.numIslands(gird);
    cout << res << endl;

    system("pause");
    return 0;
}

=================================后续待补=================================

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/980928.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

1分钟了解音频、语音数据和自然语言处理的关系

机器学习在日常场景中的应用 音频、语音数据和自然语言处理这三者正在不断促进人工智能技术的发展&#xff0c;人机交互也逐渐渗透进生活的每个角落。在各行各业包括零售业、银行、食品配送服务商&#xff09;的多样互动中&#xff0c;我们都能通过与某种形式的AI&#xff08;…

Flutter中系统Emoji通过substring裁切后无法识别导致渲染错误

Flutter中系统Emoji通过substring裁切无法识别、渲染错误 场景分析/思考寻找神马东西引起的渲染错误为什么 substring 之后就无法显示了 结论分析 substring 场景 在发布文章的时候&#xff0c;有标题和内容&#xff0c;标题可为空&#xff0c;在没有标题的情况下&#xff0c;…

大数据之MapReduce

MapReduce概述 是一个分布式的编程框架&#xff0c;MapReduce核心功能是将用户编写的业务逻辑代码和自带默认组件整合成一个完整的分布式运算程序&#xff0c;并发运行在一个Hadoop集群上。 优点&#xff1a; 易于编程&#xff0c;简单的实现一些接口&#xff0c;就可以完成一…

CentOS 7删除virbr0虚拟网卡

在CentOS 7的安装过程中如果有选择相关虚拟化的的服务安装系统后&#xff0c;启动网卡时会发现有一个以网桥连接的私网地址的virbr0网卡&#xff0c;这个是因为在虚拟化中有使用到libvirtd服务生成的&#xff0c;如果不需要可以关闭后去掉&#xff1a; 一、查看IP及网桥设备 [r…

Ajax介绍、爬取案例实战 + MongoDB存储

Ajax介绍 Ajax&#xff08;Asynchronous JavaScript and XML&#xff09;是一种用于在Web应用程序中实现异步通信的技术。它允许在不刷新整个网页的情况下&#xff0c;通过在后台与服务器进行数据交换&#xff0c;实时更新网页的一部分。Ajax的主要特点包括&#xff1a; 异步通…

前端框架 vue-admin-template的搭建运行

一介绍 1.1 下载地址 vue-element-admin是基于element-ui 的一套后台管理系统集成方案。 GitHub - PanJiaChen/vue-element-admin: :tada: A magical vue admin https://panjiachen.github.io/vue-element-admin 1.2 node.js的安装 地址下载node.js 1.6版本 CNPM Binari…

2023 IntelliJ IDEA下载、安装教程, 附详细图解

文章目录 下载与安装IDEA推荐阅读 下载与安装IDEA 首先先到官网下载最新版的IntelliJ IDEA, 下载后傻瓜式安装就好了 官网下载地址&#xff1a;https://www.jetbrains.com/ 1、下载完后在本地找到该文件&#xff0c;双击运行 idea 安装程序 2、点击 Next 3、选择安装路径&…

sqlmap --os-shell(写入木马获取getshell)

在存在sql注入处&#xff0c;可以使用--os-shell 对存在SQL注入处抓包&#xff0c;查看报错暴露出绝对路径 将POST包放入TXT文本中 启动sqlmap 读取TXT文件 python sqlmap.py -r C:\Users\南倾\Desktop\222.txt --os-shell 写入木马到文件中 echo "<?php eval($_R…

复旦-华盛顿EMBA:AI时代掘金,科技进化里的挑战与机遇

如果从去年年底ChatGPT3.5发布算起&#xff0c;AI赛道的热度已经持续飙升了半年有余。      “AI的iPhone时刻”代表什么&#xff1f;AI驱动的商业时代已经到来&#xff1f;      我们能看到担忧、恐惧、憧憬&#xff0c;但唯独不缺狂飙突进、加速进化。人类制造AI&…

ES 集群常用排查命令

说明&#xff1a;集群使用非默认端口9200&#xff0c;使用的是7116端口举例 一、常用命令 #1.集群健康状态 [wlsadminelastic-01~]$ curl -XGET "http://10.219.27.00:7116/_cluster/health?pretty" { cluster name":"cluster" "status"…

线性代数的学习和整理19,特征值,特征向量,以及引入的正交化矩阵概念

目录 1 什么是特征值和特征向量&#xff1f; 1.1 特征值和特征向量这2个概念先放后 1.2 直观定义 1.3 严格定义 2 如何求特征值和特征向量 2.1 方法1&#xff1a;结合图形看&#xff0c;直观方法求 2.1.1 单位矩阵的特征值和特征向量 2.1.2 旋转矩阵 2.2 根据严格定义…

网络协议从入门到底层原理学习(三)—— 路由

网络协议从入门到底层原理学习&#xff08;三&#xff09;—— 路由 1、简介 路由&#xff08;routing&#xff09;是指分组从源到目的地时&#xff0c;决定端到端路径的网络范围的进程 在不同网段之间转发数据&#xff0c;需要有路由器的支持 默认情况下&#xff0c;路由器…

64.C++运算符重载

目录 1.可重载\不可重载运算符 2.重载运算符&#xff1a; 3.重载运算符&#xff1a; 4.重载运算符&#xff1a;- - 5.重载运算符&#xff1a;<< 6.重载运算符&#xff1a; 运算符重载是一种C的特性&#xff0c;它允许重新定义或扩展已存在的运算符&#xff0c;以使…

语音芯片NV040D在电动车的防盗应用

在现代社会&#xff0c;人们的出行方式往往有多种多样。但电动车在交通工具中依然占据着重要地位&#xff0c;帮助人们节省了较长的通勤时间。随着电动车数量的不断增加&#xff0c;车辆的防盗也成为了人们万分重视的问题。因而选择一辆具备预警功能与故障提示的智能电动车是必…

Lua01——概述

Lua是啥&#xff1f; 官网 https://www.lua.org Lua这个名字在葡萄牙语中的意思是“美丽的月亮”&#xff0c;诞生于巴西的大学实验室。 这是一个小巧、高效且能够很好的和C语言一起工作的编程语言。 在脚本语言领域中&#xff0c;Lua因为有资格作为游戏开发的备选方案&…

WebGL 纹理——在矩形表面贴上图像

目录 WebGL要进行纹理映射&#xff0c;需遵循以下四步&#xff1a; 1. 准备好映射到几何图形上的纹理图像。 2. 为几何图形配置纹理映射方式。 3. 加载纹理图像&#xff0c;对其进行一些配置&#xff0c;以在WebGL中使用它。 4. 在片元着色器中将相应的纹素从纹理中抽取出…

密码找回安全

文章目录 密码找回安全任意秘密重置 密码找回安全 用户提交修改密码请求;账号认证:服务器发送唯一ID (例如信验证码)只有账户所有者才能看的地方&#xff0c;完成身份验证&#xff1b;身份验证:用户提交验证码完成身份验证;修改密码:用户修改密码。 任意秘密重置 登录metinfo4…

STM32 软件IIC 控制OLED 显示屏

1. 硬件IIC 实在是太难用了&#xff0c;各种卡死&#xff0c;各种发不出来数据&#xff0c;没那么多时间折腾了&#xff0c;还是用软件IIC 先吧&#xff0c;初始化 void OLED_Software_IIC_Init(void) {GPIO_InitTypeDef GPIO_InitStruct;RCC_AHBPeriphClockCmd(OLED_SOFTWARE…

分布式锁java程序怎么处理 zk与redis

curator 基于zk实现实现了一套高级功能&#xff0c;比如有分布式锁 当第二客户端加锁时&#xff0c;会先判断它前面有没有第一个节点&#xff0c;如果有就加锁失败&#xff0c;同时就对它上一个节 点加一个watcher监听器&#xff0c;当第一个节点释放或客户端A宕机时&#xff…

Redis从基础到进阶篇(四)----性能调优、分布式锁与缓存问题

目录 一、Redis 集群演变 1.1 ReplicationSentinel*高可用 1.2 ProxyReplicationSentinel(仅仅了解) 1.3 Redis Cluster 集群 (重点&#xff09; 1.3.1 Redis-cluster架构图 1.3.2 工作原理 1.3.3 主从切换 1.3.4 副本漂移 1.3.5 分片漂移 二、Redis版本历史&#xf…