1. 题目描述
2. 算法分析
深度优先搜索:往一个方向一直搜,一直搜到条件不符,返回false,然后再向上进行递归。
递归分析:
- 递归参数:当前元素的索引i 和 j,以及目标字符在字符串中的索引 k
- 递归的终止条件:
- 当匹配目标字符串,返回true;
- 返回false
- 1. 行或列索引越界,也就是到达边界了
- 2. 当前字符和目标字符不匹配
- 3. 当前字符已经被访问过了(本题使用的是,访问过一遍,就将该字符修改为 ' / ',然后合并到2中进行判断了。
递归流程:
- 先将当前的元素进行标记,然后将字符值存入临时变量temp,然后将当前board[i][j] = ' / ',代表当前已经被访问。(剪枝的过程)
- 然后再讲temp和目标字符进行对比
- 符合,就继续按照 上- 下- 左- 右 递归
- 不符合,直接返回false
- 在当前字符递归结束后,就讲temp的值,还给board[i][j]
- 为啥需要还回去呢?
- 递归搜索匹配字符串过程中,需要
board[i][j] = '/'
来防止 ”走回头路“ 。当匹配字符串不成功时,会回溯返回,此时需要board[i][j] = tmp
来”取消对此单元格的标记”。 在DFS过程中,每个单元格会多次被访问的,board[i][j] = '/'
只是要保证在当前匹配方案中不要走回头路。
3. 代码
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 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) //当匹配完了word,返回true
return true;
char temp = board[i][j];
board[i][j] = '/';
//开始递归,上 下 左 右
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] = temp;
return res;
}
}
4. 测试结果