leetbook:中级算法
类型:回溯算法
题目名:单词搜索
原题URL:https://leetcode-cn.com/leetbook/read/top-interview-questions-medium/xvkwe2/
题目描述
给定一个二维网格和一个单词,找出该单词是否存在于网格中。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
示例
示例 1:
board =
[
['A','B','C','E'],
['S','F','C','S'],
['A','D','E','E']
]
给定 word = "ABCCED", 返回 true
给定 word = "SEE", 返回 true
给定 word = "ABCB", 返回 false
限制
- board 和 word 中只包含大写和小写英文字母。
- 1 <= board.length <= 200
- 1 <= board[i].length <= 200
- 1 <= word.length <= 10^3
解题思路
1.遍历整个单词二维数组,对每个字符开始进行上下左右的dfs搜索,如果找到就返回true
2.具体dfs是一个回溯剪枝的dfs过程
3.如果字符串长度等于目标字符串的长度,说明已经找到了,退出dfs
4.如果越界,或者遍历到的当前字符和需要的目标字符串的字符不相等,直接返回
5.如果这个字符串已经被遍历到了,那么在这次遍历中将它标记为不会出现的字符’1’,以防他遍历到下面的时候又遍历回来
6.3,4,5是剪枝条件,现在上下左右进行遍历,如果找到一个地方可以返回目标字符串直接返回true
7.如果当前位置的上下左右都不能继续遍历,那么直接进行回溯
解题代码
class Solution {
public boolean exist(char[][] board, String word) {
char[] chars = word.toCharArray();
StringBuilder sb = new StringBuilder();
for(int i=0;i<board.length;i++) {
for(int j=0;j<board[0].length;j++) {
if(dfs(sb,board,i,j,chars,0)) return true;
}
}
return false;
}
public boolean dfs(StringBuilder sb,char[][] board, int i,int j,char[] chars,int idx) {
if(sb.length()==chars.length) {
return true;
}
//越界条件,直接返回
if(!inArea(board,i,j)||idx>chars.length-1||board[i][j]!=chars[idx]) return false;
sb.append(board[i][j]);
char temp = board[i][j];
board[i][j] = '1';
boolean isUsed = dfs(sb,board,i-1,j,chars,idx+1)||
dfs(sb,board,i+1,j,chars,idx+1)||
dfs(sb,board,i,j-1,chars,idx+1)||
dfs(sb,board,i,j+1,chars,idx+1);
if(!isUsed) {
sb.deleteCharAt(sb.length()-1);
board[i][j]=temp;
return false;
}else return true;
}
public boolean inArea(char[][] board, int row,int col) {
return row>=0&&col>=0&&row<board.length&&col<board[0].length;
}
}