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
Related Topics 数组 回溯算法
👍 759 👎 0
2. 题解
2.1 解法1: dfs回溯法
dfs方法作用:
判断以网格的 (i, j)位置出发,能否搜索到单词 word[k…],其中word[k…] 表示字符串 word 从第 k个字符开始的后缀子串。
如果能搜索到,则返回 true,反之返回 false。
pos 为当前遍历到的单词位置
class Solution {
int m, n;
char[][] board;
char[] word;
boolean[][] mark;
public boolean exist(char[][] board, String word) {
this.m = board.length;
this.n = board[0].length;
this.board = board;
this.word = word.toCharArray();
this.mark = new boolean[m][n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (dfs(0, i, j)) return true;
}
}
return false;
}
private boolean dfs(int pos, int i, int j) {
if (i < 0 || i >= m || j < 0 || j >= n || mark[i][j]) return false;
if (board[i][j] != word[pos]) return false;
if (pos == word.length - 1) return true;
mark[i][j] = true;
if (dfs(pos + 1, i + 1, j)) return true;
if (dfs(pos + 1, i - 1, j)) return true;
if (dfs(pos + 1, i, j + 1)) return true;
if (dfs(pos + 1, i, j - 1)) return true;
mark[i][j] = false;
return false;
}
}
写法2:
class Solution {
char[][] board;
char[] wordArray;
int m;
int n;
boolean[][] visited;
int[][] direction = new int[][]{{-1, 0}, {0, -1}, {1, 0}, {0, 1}};
public boolean exist(char[][] board, String word) {
this.board = board;
this.m = board.length;
this.n = board[0].length;
this.visited = new boolean[m][n];
this.wordArray = word.toCharArray();
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (dfs(i, j, 0)) {
return true;
}
}
}
return false;
}
public boolean dfs(int i, int j, int index) {
if (index == wordArray.length - 1 && wordArray[index] == board[i][j]) {
return true;
}
// 注意 判断条件和下标等 细节
if (index < wordArray.length - 1 && wordArray[index] == board[i][j]) {
visited[i][j] = true;
for (int k = 0; k < 4; k++) {
int newX = i + direction[k][0];
int newY = j + direction[k][1];
if (inArea(newX, newY) && !visited[newX][newY]) {
if (dfs(newX, newY, index + 1)) {
return true;
}
}
}
visited[i][j] = false;
}
return false;
}
public boolean inArea(int x, int y) {
return x < m && x >= 0 && y < n && y >= 0;
}
}
参考:
官方题解
在二维平面上使用回溯法