力扣-剑指 Offer 12. 矩阵中的路径

该博客介绍了一种利用深度优先搜索(DFS)算法在给定的二维字符网格中查找指定单词的方法。算法通过递归地遍历矩阵的相邻单元格,并使用空字符标记已访问过的元素,以防止重复访问。当找到目标单词时返回true,否则返回false。文章提供了Python和Java的代码实现,并给出了两个示例来说明算法的工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:
  给定一个 m m m x n n n 二维字符网格 b o a r d board board 和一个字符串单词 w o r d word word 如果 w o r d word word 存在于网格中,返回 t r u e true true ;否则,返回 f a l s e false false

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

例如,在下面的 3 × 4 3×4 3×4 的矩阵中包含单词 " A B C C E D " "ABCCED" "ABCCED"(单词中的字母已标出)。

在这里插入图片描述

示例 1:

输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED"

输出:true
https://leetcode-cn.com/problems/ju-zhen-zhong-de-lu-jing-lcof

示例 2:

输入:board = [["a","b"],["c","d"]], word = "abcd"

输出:false

提示

  • 1 < = b o a r d . l e n g t h < = 200 1 <= board.length <= 200 1<=board.length<=200
  • 1 < = b o a r d [ i ] . l e n g t h < = 200 1 <= board[i].length <= 200 1<=board[i].length<=200
  • b o a r d 和 w o r d 仅 由 大 小 写 英 文 字 母 组 成 board 和 word 仅由大小写英文字母组成 boardword

解题思路

递归参数:

  当前元素在矩阵 b o a r d board board 中的行列索引 i i i j j j,当前目标字符在 w o r d word word 中的索引 k k k

终止条件:

  • 返回 f a l s e false false : (1) 行或列索引越界 或 (2) 当前矩阵元素与目标字符不同 或 (3) 当前矩阵元素已访问过 ( (3) 可合并至 (2) ) 。
  • 返回 t r u e : k = l e n ( w o r d ) − 1 true: k = len(word) - 1 truek=len(word)1 ,即字符串 w o r d word word 已全部匹配。

递推工作:

  1. 标记当前矩阵元素: 将 b o a r d [ i ] [ j ] board[i][j] board[i][j] 修改为 空字符 ‘’ ,代表此元素已访问过,防止之后搜索时重复访问。
  2. 搜索下一单元格: 朝当前元素的 上、下、左、右 四个方向开启下层递归,使用 或 连接 (代表只需找到一条可行路径就直接返回,不再做后续 DFS ),并记录结果至 r e s res res
  3. 还原当前矩阵元素: 将 b o a r d [ i ] [ j ] board[i][j] board[i][j] 元素还原至初始值,即 w o r d [ k ] word[k] word[k]

返回值:

   返回布尔量 r e s res res ,代表是否搜索到目标字符串。

使用空字符(Python: ‘’ , Java/C++: ‘\0’ )做标记是为了防止标记字符与矩阵原有字符重复。当存在重复时,此算法会将矩阵原有字符认作标记字符,从而出现错误。

python3代码

class Solution:
    def exist(self, board: List[List[str]], word: str) -> bool:
        m=len(board)
        n=len(board[0]) if board else 0
        def dfs(k,i,j):
            if not 0<=i<m or not 0<=j<n  or word[k]!= board[i][j]:
                return False
            if k==len(word)-1:
                return True
            tmp=board[i][j]
            board[i][j]='#'
            res=dfs(k+1,i-1,j) or dfs(k+1,i+1,j) or dfs(k+1,i,j-1) or dfs(k+1,i,j+1)
            board[i][j]=tmp
            return res

        for i in range(m):
            for j in range(n):
                if dfs(0,i,j):
                    return True
        return False

java代码

class Solution {
    public boolean exist(char[][] board, String word) {
       char[] words=word.toCharArray();
       for(int i=0;i<board.length;i++){
           for(int j=0;j<board[0].length;j++){
               if(dfs(board,words,i,j,0))return true;
                
           }
       }
        return false;
    }
    
    boolean dfs(char[][] board,char[] word,int i,int j,int k){
        if(i>=board.length || i<0 || j>=board[0].length || j<0 || board[i][j]!=word[k])
            return false;
        if(k==word.length-1)
            return true;
        board[i][j]='\0';
        boolean res=dfs(board,word,i+1,j,k+1)|| dfs(board,word,i-1,j,k+1) ||dfs(board,word,i,j+1,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、付费专栏及课程。

余额充值