剑指 Offer 12. 矩阵中的路径
一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第25天,点击查看活动详情。
1、题目📑
给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
例如,在下面的 3×4 的矩阵中包含单词 "ABCCED"(单词中的字母已标出)。
实例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 <= 2001 <= board[i].length <= 200board和word仅由大小写英文字母组成
注意:本题与主站 79 题相同:leetcode-cn.com/problems/wo…
2、思路🧠
方法一:DFS 深度优先遍历
回溯算法实际上一个类似枚举的搜索尝试过程,换句话说就是一个个去试,枚举所有可能出现的情况,解这道题也是通过一个个去试的方法进行解题。
看到他是从矩形中的某一个位置开始向上下左右四个方向寻找,这个点可以是矩形中的任何一个点,所以代码的大致轮廓应该能写出来,也就是遍历矩形所有的点,然后从这个点开始进行4个方向探索,因为是二维数组,所以有两个for循环,代码如下
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;
}
}
}
其实这个代码的关键就是dfs该如何去写
- 递归结束条件
- 也就是所说的边界条件,超过左边界、右边界、上边界、下边界
- 还需要判断无法匹配的情况
- 如果已经扫描到word尾部,则必然是找到了
- 递归回溯:
- 接下来就是重头戏了,各位小伙伴们
- 上下左右4个方向中,只要有一个能查找到,就返回true;
- 但是在进行方向的判断时候,需要将该店进行标记,代表此元素已访问过,否则就会出现不知道现在判断到那个点,那些点已经遍历过了的问题
- 返回之前必须要将该标记的点值为初始情况,也就是复原,这样做的目的是为了回溯。
- 返回值
- 返回布尔量,代表是否搜索到目标字符串。
废话少说~~~~~上代码!
3、代码👨💻
第一次commit AC
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;
}
public boolean dfs(char [][]board, char []word,int i,int j, int index) {
//递归结束条件
if(i<0 || j<0 || i >= board.length || j >= board[0].length || board[i][j] != word[index]) {
return false;
}
//如果已经扫描到word尾部,则必然是找到了
if(word.length - 1 == index) {
return true;
}
//将当前位置进行标记
board[i][j] = '.';
boolean res = dfs(board, word, i + 1, j, index + 1) || dfs(board, word, i - 1, j, index + 1) ||
dfs(board, word, i, j + 1, index + 1) || dfs(board, word, i, j - 1, index + 1);
//还原状况,进行回溯
board[i][j] = word[index];
return res;
}
}
时间复杂度:O(3KMN) 搜索中每个字符有上、下、左、右四个方向可以选择,舍弃回头的方向,剩余3个方向,时间复杂度为O(3K),其次矩阵中共有MN个节点,所以时间复杂度为O(3KMN)
空间复杂度:O(K)
4、总结
该题目的是对搜索和回溯的思想进行练习,这个题的关键点在于dfs函数的编写,因为每一个起点都需要向它的4个方向进行查找,所以可以把它想象为一棵4叉树,就是每个节点有4个子节点(孩子),而树的遍历我们最容易想到的就是递归,自然就明白了递归和回溯。
❤️来自专栏《LeetCode基础算法题》欢迎订阅❤️
厂长写博客目的初衷很简单,希望大家在学习的过程中少走弯路,多学一些东西,对自己有帮助的留下你的赞赞👍或者关注➕都是对我最大的支持,你的关注和点赞给厂长每天更文的动力。
对文章其中一部分不理解,都可以评论区回复我,我们来一起讨论,共同学习,一起进步!