您现在的位置是:首页 > 编程 > 

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

2025-07-18 21:57:15
DFS和BFS的上下左右搜索问题(递归和迭代) 一·题目(单词搜索问题):7474ce7fa089c78a79bb071a5ca.pngnewcode题目链接: 单词搜索_牛客题霸_牛客网二·思路解释:cadc48fe8ab7d079e7d9628d.jpeg思路:个人理解是到word中的第一个元素,然后去递归的上下左右查,最后根据word的下标变化等看是否返回tru

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

一·题目(单词搜索问题):
7474ce7f99424a089c78a79bb071a5ca.png

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

二·思路解释:
c5218780adc48fe8ab7d079e7d9628d.jpeg

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

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

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

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

一开始先遍历原数组到word首元素的位置,从它开始进行递归(当然这里有种特殊情况,下面会讲到) 1·首先不是递归嘛:然后先递归终止条件这里可以根据遍历上下左右的时候出现的越界问题,总结了四个返回false的情况,根据后面的查操作也不难出另两个即可能出现查了曾经的元素+不是word中对应下标所指向的元素。-->这里就得到了递归不成立的六大终止条件。 如果我们根据实例1试到最后一次对归还会发现最后一次如果再次遍历,它应该设置一个返回真的条件 ,于是就得到了另一个返回真的条件--->也就是当word索引越界的情况 2·也就是如何递归,这里如果上面没有被返回也就是到了下面也就是到了,因此可以在真假表对应映射位置填入true,然后接着往它左右递归即可,最后呢根据递归完往回溯可以看出这里最后返回的上下左右的bool类型值应该是或的关系。 ·这里可以考虑给真假表对应的当时填入true位置复原成false(当然这里对本题解无关系)

042f42b7a4b84f5da67d844d5d8eb05.png

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

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

f4e7d1964904687ac0618dea440af1.jpeg
c8529f5eef584af68ffa76c6165084d.png
0e80e88904904527ac2a44dfda57808c.jpeg
三·解答代码:
0c77258c6074486918e0676cb50648.gif
172cfa1191df4e76a1df166c5a7cd0c0.jpeg
72628a2e70f14658a546cc7a26e2c27.jpeg
代码语言:javascript代码运行次数:0运行复制
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;

    }
};
af8d4d85da184b02a0e92779b159d1ba.jpeg
四·题目(腐烂的苹果):
a0b22d9d74479484a60119eb714c0.png

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

五·思路解释:

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

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

1·首先这道题就是我们先遍历数组然后到所有的2,之后在同时从每个2开始上下左右1覆盖成2并记录位置,并把它们就录下来方便下次用,第一批2用完后,这时是过去了一分钟故用个计时器记录一下,然后拿到刚刚保存的那些2重复操作即可,最后呢要么里面还有1没有被修改要么就是2和0了,这里如果有1那么就返回-1,否则返回这个计时器记录的就可。 2·思路的进一步转化:由上面的思路,如保存一些2的位置然后后面还要添加方便再一次使用,很容易想到队列,这里还有两个要处理 如何控制它每次都是用完保存的第一批然后再用第二批,那么此时可以用一个size记录第一批长度然后再入第二批,依次对size减减,另一个就是什么时候开始计时? 根据题意我们可以知道每次的同一批2是同时查的故这就是一分钟,因此一批过后才计数器加加。

042f42b7a4b84f5da67d844d5d8eb05.png

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

下面画图解释一下:

1a0ad2479ab4904bf5918f15b5e949.png
六·解答代码: 代码语言:javascript代码运行次数:0运行复制
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(!()){
            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 here
             for(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;
             
    }
};
​​​​

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

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:2024-10-1,如有侵权请联系 cloudcommunity@tencent 删除数组搜索dfs遍历递归

#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格

本文地址:http://www.dnpztj.cn/biancheng/1131758.html

相关标签:无
上传时间: 2025-07-18 19:29:43
留言与评论(共有 9 条评论)
本站网友 元素粘稠物
7分钟前 发表
我们就返回这个递归函数
本站网友 王婆卖瓜自卖自夸
14分钟前 发表
参数名已经指定
本站网友 网页设计入门
19分钟前 发表
故应该减去
本站网友 公司好声音
3分钟前 发表
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
本站网友 什么是分流器
7分钟前 发表
这时是过去了一分钟故用个计时器记录一下
本站网友 马鞍山房产
10分钟前 发表
然后递归下去最后返回的一定是false
本站网友 鼻咽炎
7分钟前 发表
这里为了方便记录遍历到原数组位置以及防止查时候查到已经到的原数组中元素(word中有连续重复元素在board中出现)等
本站网友 鸡精好还是味精好
9分钟前 发表
i-1