BFS的上下左右搜索问题(递归和迭代)

news/2024/9/29 8:43:16/

目录

一·题目(单词搜索问题):

二·思路解释:

三·解答代码:

​编辑   

四·题目(腐烂的苹果):

五·思路解释:

六·解答代码:   

             ​​​​


 

一·题目(单词搜索问题):

newcode题目链接: 单词搜索_牛客题霸_牛客网

二·思路解释:

思路:个人理解是找到word中的第一个元素,然后去递归的上下左右查找,最后根据word的下标变化等看是否返回true

下面具体说一下个人思路(也是根据大佬悟出来的):这里有点明显想考的是递归的使用,这里为了方便记录遍历到原数组位置

以及防止查找时候查到已经找到的原数组中元素(word中有连续重复元素在board中出现)等,因此不方便在原数组里面操作,因此重新建一个二维数组(这里个人称作真假表->主要记录遍历原数组找到元素位置,给它在真假表中用true标记,而默认是false,这里标记它的路径也能防止“走重的操作了”).

因此这里首先建立一个递归函数,首先要想完成这个操作需要哪些参数等呢? word和它的索引 ,board和它的下标i,j,以及我们的真假表(这里下标直接用board的i,j即可);

一开始先遍历原数组找到word首元素的位置,从它开始进行递归(当然这里有种特殊情况,下面会讲到)

1·首先不是递归嘛:然后先找递归终止条件这里可以根据遍历上下左右的时候出现的越界问题,总结了四个返回false的情况,根据后面的查找操作也不难找出另两个即可能出现查找了曾经找的元素+不是word中对应下标所指向的元素。-->这里就得到了递归不成立的六大终止条件。   如果我们根据实例1试到最后一次对归还会发现最后一次如果再次遍历,它应该设置一个返回真的条件 ,于是就得到了另一个返回真的条件--->也就是当word索引越界的情况

2·也就是如何递归,这里如果上面没有被返回也就是到了下面也就是找到了,因此可以在真假表对应映射位置填入true,然后接着往它左右递归即可,最后呢根据递归完往回溯可以看出这里最后返回的上下左右的bool类型值应该是或的关系。

3·这里可以考虑给真假表对应的当时填入true位置复原成false(当然这里对本题解无关系)

这里有一个细节问题;也就是上面说的,这里找到对应word[0],我们就返回这个递归函数,这里是错误的(表示掉过坑),这里可能是这种情况:["CAA","AAA","BCD"] "AAB"-->这里如果找到第一个A,然后递归下去最后返回的一定是false,然而此例子返回的应该是true,因此如果它是false就接着遍历board继续找,然后再次递归, 因此这里如果递归函数返回false不一定题解真实false,但是如果返回true则题解一定是true。,因此注意好这个基本到这就没什么问题了。

下面画图以实例1为例子解释如何递归的:

 

三·解答代码:

                  

class Solution {
public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** * @param board string字符串vector * @param word string字符串 * @return bool布尔型*/bool recursion_find(vector<string>& board,int i,int j, string word,int word_index,vector<vector<bool>>TF_graph){if(word_index==word.size()) return true;if(i<0||i>=board.size()||j<0||j>=board[0].size()||TF_graph[i][j]==true||board[i][j]!=word[word_index]) return false;TF_graph[i][j]=true;bool target_on=recursion_find(board,i-1,j,word,word_index+1,TF_graph);bool target_under=recursion_find(board,i+1,j,word,word_index+1,TF_graph);bool target_left=recursion_find(board,i,j-1,word,word_index+1,TF_graph);bool target_right=recursion_find(board,i,j+1,word,word_index+1,TF_graph);// TF_graph[i][j]=false;return  target_on||target_under||target_left|| target_right;}bool exist(vector<string>& board, string word) {int m=board.size();int n=board[0].size();vector<vector<bool>>TF_graph(m,vector<bool>(n,false));for(int i=0;i<m;i++){for(int j=0;j<n;j++){if(board[i][j]==word[0]){//return recursion_find(board,i,j,word,0,TF_graph);if (recursion_find(board,i,j,word,0,TF_graph)) {return true;}}}}return false;}
};

   

四·题目(腐烂的苹果):

nowcoder题目链接:腐烂的苹果_牛客题霸_牛客网 

五·思路解释:

思路:这里虽然是bfs有两种思路的方向可以让我们完成代码的操作,一个就是递归,另一个就是迭代,这里考虑一下迭代完成,

即通过选择合容器配合出入以及循环完成。下面讲解一下迭代应用于本题的具体思路:

1·首先这道题就是我们先遍历数组然后找到所有的2,之后在同时从每个2开始上下左右找1覆盖成2并记录位置,并把它们就录下来方便下次用,第一批2用完后,这时是过去了一分钟故用个计时器记录一下,然后拿到刚刚保存的那些2重复操作即可,最后呢要么里面还有1没有被修改要么就是2和0了,这里如果有1那么就返回-1,否则返回这个计时器记录的就可。

2·思路的进一步转化:由上面的思路,如保存一些2的位置然后后面还要添加方便再一次使用,很容易想到队列,这里还有两个要处理

如何控制它每次都是用完保存的第一批然后再用第二批,那么此时可以用一个size记录第一批长度然后再入第二批,依次对size减减,另一个就是什么时候开始计时? 根据题意我们可以知道每次的同一批2是同时查找的故这就是一分钟,因此一批过后才计数器加加

 

当然这里还有一个更细节问题需要处理就是我们的计时器:先说结论这里计时器count,如果找不到1,那么应该返回的是cout-1;为什么呢?这里不是,每次队列里每减完一批2所在位置那么count就加加,我们可以根据例1推算出,结论:当走到最后的那批,此时这批是无法找到再下一批的但是还会使得count++,故这次应该不算,但是我们把它算进去了,故应该减去。

 

下面画图解释一下: 

 

六·解答代码:   

class Solution {
public:/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** * @param grid int整型vector<vector<>> * @return int整型*/queue<pair<int,int>>q;int count=0;
//这里写一个函数判断下标是否越界问题:bool judge(vector<vector<int> >& grid,int m,int n){if (m<0||m>=grid.size()||n<0||n>=grid[0].size()) return false;else return true;}//子函数利用容器特点把递归转换成迭代解决:void bfs(vector<vector<int> >& grid,int &count){while(!q.empty()){int size=q.size();while(size--){pair<int,int> f=q.front();q.pop();int i=f.first;int j=f.second;if(judge(grid,i,j-1)&&grid[i][j-1]==1){q.push(make_pair(i,j-1));grid[i][j-1]=2;}if(judge(grid,i,j+1)&&grid[i][j+1]==1){q.push(make_pair(i,j+1));grid[i][j+1]=2;}if(judge(grid,i-1,j)&&grid[i-1][j]==1){q.push(make_pair(i-1,j));grid[i-1][j]=2;}if(judge(grid,i+1,j)&&grid[i+1][j]==1){q.push(make_pair(i+1,j));grid[i+1][j]=2;}}count++;}}int rotApple(vector<vector<int> >& grid) {// write code herefor(int i=0;i<grid.size();i++){for(int j=0;j<grid[0].size();j++){if(grid[i][j]==2){q.push(make_pair(i,j));}}}bfs(grid,count);for(int i=0;i<grid.size();i++){for(int j=0;j<grid[0].size();j++){if(grid[i][j]==1) return -1;}}return count-1;}
};

             ​​​​

 若有补充希望大佬们留言.        


http://www.ppmy.cn/news/1531849.html

相关文章

Qt Creator 集成开发环境 常见问题

1.QtCreator中三种不同编译版本 debug、release、profile 的区别 在 Qt Creator 中&#xff0c;Debug、Release 和 Profile 是三种不同的构建配置&#xff0c;它们主要用于在开发过程中生成不同类型的可执行文件。它们的区别如下&#xff1a; 1.1 Debug&#xff08;调试版本&…

maven基础/java包管理器

Maven 在构建java项目的时候&#xff0c;总是会碰到下载依赖和对项目结构的疑问&#xff0c;以下内容就是我对现在最常用之一的java包管理器maven的学习笔记 一、情景和作用以及前置步骤 1.1情景和作用 解决依赖管理和项目构建 核心文件&#xff1a;pom.xml&#xff0c;类似…

web - RequestResponse

##Request&Response 1&#xff0c;Request和Response的概述 Request是请求对象&#xff0c;Response是响应对象。这两个对象在我们使用Servlet的时候有看到&#xff1a; 此时&#xff0c;我们就需要思考一个问题request和response这两个参数的作用是什么? request:获取请…

windows端后端运行python程序,类似nohup

假如是py文件&#xff1a; start /min python test.py 相当于Linux中&#xff1a; nohup python test.py &如果是Pyinstaller打包的exe程序&#xff1a; start /b cmd /c xxx.exe > output.log 2>&amp;1其中 /b 表示在新窗口中打开程序&#x…

Linux云计算 |【第四阶段】RDBMS1-DAY2

主要内容&#xff1a; 常用函数&#xff08;函数分类1&#xff1a;单行、分组&#xff1b;函数分类2&#xff1a;字符、数学、日期、流程控制&#xff09;、分组查询group by、连接查询 一、常用函数 1. 按使用方式分类 ① 单行函数 单行函数&#xff08;Scalar Functions&…

爬虫技术深潜:探究 JsonPath 与 XPath 的语法海洋与实战岛屿

Python爬虫中JSON与XML字符串的XPath和JsonPath过滤语法区别对比 在信息爆炸的互联网时代&#xff0c;数据抓取成为了获取宝贵信息的关键技能。对于技术爱好者&#xff0c;特别是Python程序员来说&#xff0c;熟练掌握JSON和XML数据解析方法至关重要。本文旨在深入探讨这两种格…

详解2024 openAi最新gpt o1模型分析

探索 GPT 的 O1 模型:一场人工智能的革命 在人工智能领域,尤其是自然语言处理(NLP)领域,模型的不断迭代和升级为我们带来了前所未有的机遇。最近,OpenAI 发布了全新的 O1 模型,这一创新不仅在技术上取得了重大突破,也为各行各业的应用提供了更多可能性。本文将深入探讨…

Scrapy框架入门

一、Scrapy简介 Scrapy是一款快速而强大的web爬虫框架&#xff0c;基于Twisted的异步处理框架、Twisted是事件驱动的。 Scrapy是由python实现的爬虫框架&#xff1a;架构清晰、可扩展性强、可以灵活完成需求。 一、Scrapy应用 scrapy及其他模块的安装 pip3 install scrapy…