目录
一、题目
给定一个 m * n
二维字符网格 board
和一个字符串单词 word
。如果 word
存在于网格中,返回 true
;否则,返回 false
。单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
二、思路
基于回溯法+深度优先搜索(DFS)来做:
将单词首字母与矩阵的元素对比、若有元素和word首字母一致、则以此为起点遍历右上左下四个方向、看矩阵元素是否存在于word第二个字符匹配、依次的上下左右都遍历一下、若到达word末尾字符且能匹配到矩阵的元素,返回true、否则返回false。
1、先规定搜索方向,依次右、上、作、下的其余三个方向搜索。
2、匹配就继续往下一个元素的上下左右搜索。
3、注意是否访问、超出边界、是否匹配到等条件。
三、代码
class Solution {
// 定义n、m
int n;
int m;
// 剩余单词长度
int len;
// 用于标记该元素是否被使用
boolean[][] visited;
public boolean exist(char[][] board, String word) {
this.n = board.length;
this.m = board[0].length;
this.len=word.length();
this.visited = new boolean[n][m];
// 遍历二阶矩阵
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
boolean existFlag = dfs(board,i,j,0,word);
if(existFlag){
return true;
}
}
}
return false;
}
boolean dfs(char[][] board,int i,int j ,int k,String word){
// 先判断是否出界
if(i<0||i>=n||j<0||j>=m){
return false;
}
// 是否访问过了
if(visited[i][j]){
return false;
}
// 字符串是否相等
if(board[i][j]!=word.charAt(k)){
return false;
}
// 匹配到此字符
if(k==len-1){
return true;
}
// 递归搜索
// 右边、上、左、下四个方向搜索
visited[i][j]=true;
boolean existFlag = dfs(board, i, j + 1, k + 1, word)
||dfs(board,i+1,j,k+1,word)
||dfs(board,i,j-1,k+1,word)
||dfs(board,i-1,j,k+1,word);
// 回溯一下
visited[i][j]=false;
return existFlag;
}
}
对于上述代码、空间复杂度m*n,时间复杂度mn*3len
执行结果
四、总结
回溯法解题的过程大致可以用一个树形结构表示、每一步都可视作新的节点、其中一步选择某个选项后、下一步又是新的选择、如此重复、直至达到最终状态。回溯法通常是使用递归代码实现。