单词搜索
难度:
标签:
题目描述
给定一个 m x n
二维字符网格 board
和一个字符串单词 word
。如果 word
存在于网格中,返回 true
;否则,返回 false
。
单词必须按照字母顺序,通过相邻的单元格内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母不允许被重复使用。
示例 1:
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED" 输出:true
示例 2:
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "SEE" 输出:true
示例 3:
输入:board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCB" 输出:false
提示:
m == board.length
n = board[i].length
1 <= m, n <= 6
1 <= word.length <= 15
board
和word
仅由大小写英文字母组成
进阶:你可以使用搜索剪枝的技术来优化解决方案,使其在 board
更大的情况下可以更快解决问题?
代码结果
运行时间: 204 ms, 内存: 17.1 MB
/*
题目思路:
1. 使用DFS(深度优先搜索)和Java Stream API来处理二维网格和字符串的匹配问题。
2. 遍历二维网格的每个单元格,使用Stream和filter方法筛选出符合条件的起始点,进行递归搜索。
3. 使用Streams的任何操作都必须避免副作用,标记和回溯需要考虑副作用问题。
*/
import java.util.stream.IntStream;
public class Solution {
public boolean exist(char[][] board, String word) {
return IntStream.range(0, board.length)
.boxed()
.flatMap(i -> IntStream.range(0, board[0].length)
.filter(j -> dfs(board, word, i, j, 0))
.boxed())
.findFirst()
.isPresent();
}
private boolean dfs(char[][] board, String word, int i, int j, int index) {
if (index == word.length()) return true;
if (i < 0 || j < 0 || i >= board.length || j >= board[0].length || board[i][j] != word.charAt(index))
return false;
char temp = board[i][j];
board[i][j] = ' ';
boolean found = dfs(board, word, i + 1, j, index + 1)
|| dfs(board, word, i - 1, j, index + 1)
|| dfs(board, word, i, j + 1, index + 1)
|| dfs(board, word, i, j - 1, index + 1);
board[i][j] = temp;
return found;
}
}
解释
方法:
这个题解使用回溯法来解决单词搜索问题。从二维网格的每个位置开始,如果该位置的字符与目标单词的第一个字符匹配,就开始回溯搜索。在回溯搜索过程中,选择当前位置的上、下、左、右四个相邻位置作为下一步搜索的选择。对于每个选择,首先判断是否满足有效性条件(未越界、未访问过、字符匹配),如果满足则标记为已访问,将字符加入路径并递归搜索下一层。如果搜索到目标单词的所有字符,则返回 True。如果所有选择都搜索完毕仍未找到目标单词,则回溯到上一层,撤销当前选择的访问标记和路径。如果从所有起始位置的搜索都无法找到目标单词,则返回 False。
时间复杂度:
O(m*n*4^L)
空间复杂度:
O(L)
代码细节讲解
🦆
在回溯过程中,如果当前路径长度与目标单词长度相等,为什么可以直接返回True,而不再检查路径中的字符是否完全匹配目标单词?
▷🦆
为什么在每一步回溯中,选择的顺序是上、下、左、右,改变这个顺序会对算法的效率产生影响吗?
▷🦆
在递归函数中,为什么要使用path和visited两个结构,而不是仅用visited来记录访问过的位置和路径信息?
▷🦆
对于边界条件的处理,如何确保在递归过程中不会访问到二维网格之外的元素?
▷相关问题
单词搜索 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"] 输出:[]
提示:
m == board.length
n == board[i].length
1 <= m, n <= 12
board[i][j]
是一个小写英文字母1 <= words.length <= 3 * 104
1 <= words[i].length <= 10
words[i]
由小写英文字母组成words
中的所有字符串互不相同