剑指 Offer 12. 矩阵中的路径

本文介绍了一种使用深度优先搜索(DFS)解决在给定二维字符网格中寻找目标单词的问题。该算法涉及到栈的概念,当遇到不匹配的字符或超出边界时返回false,否则继续搜索。在搜索过程中,为了避免回溯到已访问过的单元格,使用临时修改字符的方法进行标记。详细解析了代码实现,并通过实例解释了递归的本质和栈的工作原理。
摘要由CSDN通过智能技术生成

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

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

例如,在下面的 3×4 的矩阵中包含单词 “ABCCED”(单词中的字母已标出)。
url:https://leetcode.cn/problems/ju-zhen-zhong-de-lu-jing-lcof/
示例 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

提示:

1 <= board.length <= 200
1 <= board[i].length <= 200
board 和 word 仅由大小写英文字母组成

做此题之前最好看一下 视频讲解
这个迷宫问题跟这个题很类似
首先了解递归的本质,递归的本质是栈,
在这里插入图片描述
递归每进去一次都会新开辟一个栈空间,可以看到输入test(4),进去后n>2,所以进入了test(3),这个时候其实是新的栈空间,每次栈空间内都会存放有n,就是4的那个栈内存放的n为4, 3那个栈内存放的n为3,输出时候并不会先输出4,因为栈是现金后出的,最后n为2的时候,不满足继续递归的条件了,这个时候会优先输出最后执行的函数,也就是2的那个栈空间,这时候打印出n=2,然后继续抛出栈顶的元素,这时候抛出3的那个栈,这个栈内存放的是n=3,一定要注意,每个栈空间内,存放的数据都是独立的,记录着进入时的状态。

然后看这道题,
在这里插入图片描述
迷宫问题就是,有墙阻拦,踩踏过的点不用在踩了,这个其实也一样,不满足连续word的地方也可以理解为一堵墙,大神思路:https://leetcode.cn/problems/ju-zhen-zhong-de-lu-jing-lcof/solution/mian-shi-ti-12-ju-zhen-zhong-de-lu-jing-shen-du-yo/这个里面那个ppt很生动形象

public bool Exist(char[][] board, string word) {
        int k = 0;
        for(int i = 0; i< board.Length;i++) //开始遍历数组,找第一个字母
        {
            for(int j = 0;j<board[0].Length;j++)
            {
            //从起点0,0出发
                if( dfs(board,word,i,j,k) )return true;
                //为真才返回true,若为假,也不返回false,接着遍历,找第一个点
            }
        }
        return false;
    }

public bool dfs(char[][] board,string word,int i,int j,int k)
    {
    	//超过边界了直接返回false,如果当前矩阵所在位置的元素跟单词目前的不一样,直接返回
        if(i>board.Length-1 || i<0 || j>board[0].Length-1 || j<0 || board[i][j]!=word[k])       
        {
          return false;
        }        
      
      //如果当前相同,且已经完全匹配,返回true
        if(k == word.Length - 1) return true; //字符串匹配完成
	/*
		//为什么要标记,因为要表示这个节点已经走过了,
		例如 
		上图的ABCE,走过A,再去检查S,发现字符不一样,dfs(board,word,i+1,j,k+1) 直接返回了false,就去检查dfs(board,word,i,j+1,k+1) B,
		发现字符一样不越界,那么就检查B的下 右 上 左,总不能再去往左边检查A吧,那么就绕回去了,要知道,
		每进一次栈,数据都存了一份当前的副本,进入B的时候,B内记录的有board[i][j] = '\0' ,就是B暂时变为 '\0',代表走过了,
		同时每个栈内记录了word[k],是进入那个栈时候的word[k],即记录board[i][j] 其实原本放的是B,以后下面万一哪一步一路没走通(打比方),
		需要回到A回来从其他路开始走的时候,比如以前是从A往下到S,从S走到最后比如F,发现不行,走不通,这个时候你要给F和B和A变回他们当初的样子的,
		他们不是'\0',他们最初的数字被存放在他们自己的栈内,就是word[k]。
		*/
        board[i][j] = '\0' ; //标志为:本次已经遍历过了
        bool res = dfs(board,word,i+1,j,k+1) || dfs(board,word,i,j+1,k+1)
                || dfs(board,word,i-1,j,k+1) || dfs(board,word,i,j-1,k+1);
                    //下 右 上 左
        board[i][j] = word[k]; //还原原来位置应该是什么
        return res;
    }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值