来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/word-search-ii
题目描述:
给定一个 m x n 二维字符网格 board 和一个单词(字符串)列表 words,找出所有同时在二维网格和字典中出现的单词。
单词必须按照字母顺序,通过 相邻的单元格 内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。
示例 1:
输入:board = [["o","a","a","n"],["e","t","a","e"],["i","h","k","r"],["i","f","l","v"]], words = ["oath","pea","eat","rain"]
输出:["eat","oath"]
示例 2:
输入:board = [["a","b"],["c","d"]], words = ["abcb"]
输出:[]
题目分析:
- 同一个单元格内的字母在 使用。
- 单词必须按照字母顺序,通过 内的字母构成.
思路:
- 初始化一个行列和网格相同的数组,用来记录使用中的字符,避免重复使用
- 深度遍历,按照上,下, 左,右 四个方向依次试探,判断该方向的字符是否等于对应word的字符。相等则继续往四个方向试探,否则返回上一个坐标。
(这种方式时间复杂度只超过15%,不属于最优解)
代码实现:
class Solution {
public char[][] board;
public int[][] mark;
public List<String> result = new ArrayList();
public int row;
public int col;
public boolean flag;
public List<String> findWords(char[][] board_, String[] words) {
board = board_;
row = board.length; // 行
col = board[0].length; // 列
int len = words.length; // 单词数量
mark = new int[row][col];
for (int k = 0; k < len; k++) { // 循环判断每个单词是否在表格中
String word = words[k];
char word_char = word.charAt(0);
out:
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
char str = board[i][j];
if (str == word_char) {
flag = true;
dfs(i, j, 0, words[k]);
if (!flag) break out; // 找到单词,继续判断下一个单词
}
}
}
}
return result;
}
public void dfs(int m, int n, int idx, String word) {
if (!flag) return; // 已经在表格中找到单词,快速返回.
if (m < 0 || m >= row || n < 0 || n >= col || idx >= word.length()) { // 超过边界,直接返回.
return;
}
if (mark[m][n] == 1) return; // 该字符已经使用过,直接返回.
if (word.charAt(idx) != board[m][n]) { // 该字符和单词中对应字符不相同,直接返回.
return;
}
if (idx == word.length() - 1){ // 找到了所有单词.
result.add(word); // 将找到的单词保持到容器.
flag = false; // 快速返回.
return; // 返回.
}
mark[m][n] = 1; // 标记表格中(m,n)坐标的字符使用ing
dfs(m + 1, n, idx + 1, word); // 往下找
dfs(m - 1, n, idx + 1, word); // 往上找
dfs(m, n + 1, idx + 1, word); // 往右找
dfs(m, n - 1, idx + 1, word); // 往左找
mark[m][n] = 0; // 将表格中(m,n)坐标的字符恢复为未使用状态.
}
}