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

介绍

深度优先搜索(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.rhkb.cn/news/122921.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Jenkins实现基础CD操作

操作截图 在Jenkins里面设置通过标签进行构建 在Jenkins中进入项目&#xff0c;配置以下 将execute shell换到invoke top-level maven targets之前 在gitlab中配置标签 代码迭代新的版本 项目代码迭代 修改docker-compose.yml 提交新版本的代码 在Jenkins中追加新…

Linux CentOS7设置时区

在Linux系统中&#xff0c;默认使用的是UTC时间。 即使在安装系统的时候&#xff0c;选择的时区是亚洲上海&#xff0c;Linux默认的BIOS时间&#xff08;也称&#xff1a;硬件时间&#xff09;也是UTC时间。 在重启之后&#xff0c;系统时间会和硬件时间同步&#xff0c;如果…

rtthread下spi device架构MCP25625驱动

1.CAN驱动架构 由于采用了RTT的spi device架构&#xff0c;不能再随心所遇的编写CAN驱动 了&#xff0c;之前内核虽然采用了RTT内核&#xff0c;但是驱动并没有严格严格按RTT推荐的架构来做&#xff0c;这次不同了&#xff0c;上次是因为4个MCP25625挂在了4路独立的SPI总线上&…

git修改默认分支

git checkout 分支 切换到当前分支 git branch --set-upstream-toorigin/complete(远程分支名) 设置当前分支的上游分支为远程分支complete git branch --unset-upstream master 取消master上游分支的身份 现在&#xff0c;使用git commit&#xff0c;git push 命令可以直接…

2023年亲测有效----树莓派启动时自动邮件上报ip

2023年亲测 树莓派启动时自动邮件上报ip 首先开启qq邮箱smtp服务shell文件内容启动自动执行python文件注意事项 首先开启qq邮箱smtp服务 然后点击开启就会有授权码 shell文件内容 在自己的shell里&#xff0c;运行echo $PATH&#xff0c;把内容覆盖下面的path。 功能 作用就…

大数据技术之Hadoop:使用命令操作HDFS(四)

目录 一、创建文件夹 二、查看指定目录下的内容 三、上传文件到HDFS指定目录下 四、查看HDFS文件内容 五、下载HDFS文件 六、拷贝HDFS文件 七、HDFS数据移动操作 八、HDFS数据删除操作 九、HDFS的其他命令 十、hdfs web查看目录 十一、HDFS客户端工具 11.1 下载插件…

【vue2第十五章】VueRouter 路由配置(VueRouter)与使用 和 router-link与router-view标签使用

单页面应用 与 多页面应用 单页面应用&#xff08;Single-Page Application&#xff0c;SPA&#xff09;和多页面应用&#xff08;Multi-Page Application&#xff0c;MPA&#xff09;是 Web 应用程序的两种不同架构方式。它们在页面加载和交互方式上有所区别。 单页面应用&a…

RabbitMQ:hello结构

1.在Linux环境上面装入rabbitMQ doker-compose.yml version: "3.1" services:rabbitmq:image: daocloud.io/library/rabbitmq:managementrestart: alwayscontainer_name: rabbitmqports:- 6786:5672- 16786:15672volumes:- ./data:/var/lib/rabbitmq doker-compos…

【网络编程】TCP传输控制协议(Transmission Control Protocol)

(꒪ꇴ꒪ )&#xff0c;Hello我是祐言QAQ我的博客主页&#xff1a;C/C语言&#xff0c;数据结构&#xff0c;Linux基础&#xff0c;ARM开发板&#xff0c;网络编程等领域UP&#x1f30d;快上&#x1f698;&#xff0c;一起学习&#xff0c;让我们成为一个强大的攻城狮&#xff0…

【回眸】牛客网刷刷刷!(八)——中断专题

目录 前言 1、在CortexM内核中&#xff0c;当系统响应一个中断时 2、用与非门和或非门可以实现其他基本门电路。进而实现任何逻辑电路 3、cpu interface提供了功能包含 4、以Cortex-M3内核为例&#xff0c;如果某个中断在得到响应之前&#xff0c;其请求信号以若干的脉冲的…

超越时间与人力的软件开发智慧:《人月神话》

目录 1、写在前面2、沟通&#xff01;沟通&#xff01;沟通&#xff01;3、“银弹论”4、“人月神话”不能成立的原因5、影响力6、图书推荐 1、写在前面 《人月神话》是由计算机科学家弗雷德里克布鲁克斯所著的一本经典著作&#xff0c;首次出版于1975年。这本书以一个个小故事…

SSL证书系列--又拍云Let’s Encrypt免费DV SSL证书使用教程

原文网址&#xff1a;SSL证书系列--又拍云Let’s Encrypt免费DV SSL证书使用教程_IT利刃出鞘的博客-CSDN博客 简介 本文介绍如何使用又拍云部署Let’s Encrypt免费DV SSL证书。 一、了解Let’s Encrypt 了解和关注SSL证书的朋友&#xff0c;似乎没有理由不知道 Let’s Encr…

苹果与芯片巨头Arm达成20年新合作协议,将继续采用芯片技术

9月6日消息&#xff0c;据外媒报道&#xff0c;芯片设计巨头Arm宣布在当地时间周二提交给美国证券交易委员会&#xff08;SEC&#xff09;的最新IPO文件中&#xff0c;透露与苹果达成了一项长达20年的新合作协议&#xff0c;加深了双方之间的合作关系。 报道称&#xff0c;虽然…

进入低功耗和唤醒

休眠模式 进入休眠模式 如果使用 WFI 指令进入睡眠模式&#xff0c;则嵌套向量中断控制器 (NVIC) 确认的任意外设中断都会 将器件从睡眠模式唤醒。 如果使用 WFE 指令进入睡眠模式&#xff0c;MCU 将在有事件发生时立即退出睡眠模式。唤醒事件可 通过以下方式产生&#xff…

jvs-智能bi(自助式数据分析)9.1更新内容

​jvs-智能bi更新功能 1.报表增加权限功能&#xff08;服务、模板、数据集、数据源可进行后台权限分配&#xff09; 每个报表可以独立设置权限&#xff0c;通过自定义分配&#xff0c;给不同的人员分配不同的权限。 2.报表新增执行模式 可选择首次报表加载数据为最新数据和历…

搜索二维矩阵 II

题目链接 搜索二维矩阵 II 题目描述 注意点 矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。 每列的元素从上到下升序排列。 解答思路 最初想到使用深度优先遍历剪枝实现&#xff0c;但是运行后超出时间限制了可以直接遍历整个矩阵查找&#xff0c;虽然不超时…

升级iOS 17出现白苹果、不断重启等系统问题怎么办?

iOS 17发布后了&#xff0c;很多果粉都迫不及待的将iphone/ipad升级到最新iOS17系统&#xff0c;体验新系统功能。 但部分果粉因硬件、软件的各种情况&#xff0c;导致升级系统后出现故障&#xff0c;比如白苹果、不断重启、卡在系统升级界面等等问题。 如果遇到了这些系统问题…

python 创建 Telnet 客户端

目录 前言 1. Telnet 客户端框架 2. Telnet 代码分解 2.1 基于 TK 创建会话窗口 2.1.1 创建 Text 文本控件 2.1.2 创建 Frame 容器 2.1.2.1 基于 Frame 容器创建主机地址输入框 2.1.2.1.1 主机地址输入框绑定焦点事件 2.1.2.2 创建 Telnet 连接按钮控件 2.1.2.3 创建…

小程序如何上传微信聊天记录的文件

wx.chooseMessageFile({count: 10,type: image,success (res) {// tempFilePath可以作为img标签的src属性显示图片const tempFilePaths res.tempFiles} })参数说明 回调函数说明

【区块链 | IPFS】浅谈 | IPFS数据存储原理

IPFS在数据存储方面采用的是分散式的文件存储,区别于HTTP协议的位置寻址,IPFS是基于内容寻址,当文件上传到IPFS节点存储时,节点会对文件进行Merkle DAG(默克尔有向无环图)的格式组织分块存储,在存储完毕后,文件将以Merkle DAG的根哈希数来表示该文件,用户可以从IPFS构…