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

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

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

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 >& 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 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;

}

};

         ​​​​

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

相关文章
|
机器学习/深度学习 搜索推荐 算法
深度学习推荐系统架构、Sparrow RecSys项目及深度学习基础知识
深度学习推荐系统架构、Sparrow RecSys项目及深度学习基础知识
375 0
C盘满了,清理C盘常用步骤!
真正的深度清理c盘 放心,大胆的删除! 第一步 删除临时文件     1.win+R调出命令框     2.输入%temp% 点击确定
|
监控 安全 数据挖掘
Python自动化交易
【8月更文挑战第7天】随着科技发展,自动化交易成为高效智能的投资方式。Python因其实用性和灵活性,在此领域大放异彩。本文介绍使用Python进行自动化交易的流程,包括获取市场数据、制定交易策略、执行交易、风险管理、监控与优化、实时监控及通知、心态管理、安全与隐私保护以及持续学习与优化等方面,并提供了具体的代码示例。通过这些步骤,读者可以构建自己的自动化交易系统,实现稳健的投资回报。
|
10月前
|
存储 安全 Java
🌟Java零基础-反序列化:从入门到精通
【10月更文挑战第21天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
243 5
|
11月前
|
算法 大数据 Python
局部异常因子(LOF)
局部异常因子(LOF)
|
人工智能 弹性计算 自然语言处理
芯片竞争格局及最佳匹配场景|开发者分享会
今天分享的内容来自阿里云智能解决方案架构师冯英飞的“芯片竞争格局及最佳匹配场景”。本文主要从ARM芯片市场竞争与生态分析、倚天竞争力分析以及优势业务场景介绍这三个内容进行讲解。
130202 3
|
11月前
|
计算机视觉 Python
Python操作PDF文件
Python操作PDF文件
214 1
|
11月前
|
机器学习/深度学习 Unix 开发者
python的环境管理工具有哪些
python的环境管理工具有哪些
252 0
|
JSON 小程序 前端开发
小程序中使用npm安装vant组件实现按需引入减少代码包大小,避免触发用户隐私协议
微信小程序按需引入 vant 组件,自动清除项目中未使用的 vant 组件,减少代码包大小,避免因未使用到的 vant 组件触发隐私协议提交审核时被拒
小程序中使用npm安装vant组件实现按需引入减少代码包大小,避免触发用户隐私协议
|
IDE 编译器 开发工具
【Qt】如何搭建Qt开发环境
【Qt】如何搭建Qt开发环境