题目
题解
在经过几道回溯题之后,终于迎来了回溯搜索类型题,而且还是道二维平面上的回溯,不是简单套模板就可以ac的了
设函数check(i,j,k) 表示判断以网格的 (i,j) 位置出发,能否搜索到单词 word[k…]
- 如果board[i][j]!=word[k],返回false
- 如果已经访问到字符串末尾,并且对应字符依然匹配,返回true
- 否则,遍历当前位置的所有相邻位置。如果从某个相邻位置出发,能够搜索到子串word[k+1…]则返回true,否则返回false
对每一个位置都调用check(i,j,0) 进行检查,只要有一处返回true,就说明网格中能找到对应单词
为防止重复遍历相同的位置,维护一个和board等大的visited数组,用于标识每个位置是否被访问过。遍历相邻位置时,跳过已经遍历过的位置。
class Solution {
int m,n;
boolean[][] visited;
public boolean exist(char[][] board, String word) {
m=board.length;
n=board[0].length;
visited=new boolean[m][n];
for(int i=0;i<m;i++){
for(int j=0;j<n;j++){
//对于每个位置都进行检查,有一处满足即返回true
if(backtrack(board,word,i,j,0))
return true;
}
}
return false;
}
public boolean backtrack(char[][] board,String word,int i,int j,int k){
//有一个字符不等就返回false
if(board[i][j]!=word.charAt(k))
return false;
//该字符相等,且已到单词末尾,说明全部匹配
else if(k==word.length()-1)
return true;
visited[i][j]=true;
//遍历当前位置的四个相邻位置
int[][] direction={{0,1},{1,0},{0,-1},{-1,0}};//偏移量数组
for(int[] dir:direction){
int x=i+dir[0],y=j+dir[1];
if(x>=0&&x<m&&y>=0&&y<n){
if(!visited[x][y]&&backtrack(board,word,x,y,k+1))
return true;
}
}
visited[i][j]=false;//回溯
return false;
}
}
注:偏移量数组在二维平面内是经常使用的,可以把它的设置当做一个技巧,并且在这个问题中,偏移量数组内的 4 个偏移的顺序无关紧要
时间复杂度: O ( m n ∗ 3 l ) O(mn*3^l) O(mn∗3l),其中l为单词word长度,在每次调用函数 check 时,除了第一次可以进入 4 个分支以外,其余时间我们最多会进入 3 个分支(因为每个位置只能使用一次,所以走过来的分支没法走回去)。检查一次的时间复杂度是 O ( 3 l ) O(3^l) O(3l),共需O(mn)次检查。
空间复杂度: O ( m n ) O(mn) O(mn),额外的visited数组。