212. 单词搜索 II
1. 题目
给定一个 m x n
二维字符网格 board
和一个单词(字符串)列表 words
, 返回所有二维网格上的单词 。
单词必须按照字母顺序,通过 相邻的单元格 内的字母构成,其中“相邻”单元格是那些水平相邻或垂直相邻的单元格。同一个单元格内的字母在一个单词中不允许被重复使用。
示例 1:
1 | 输入:board = [["o","a","a","n"],["e","t","a","e"],["i","h","k","r"],["i","f","l","v"]], words = ["oath","pea","eat","rain"] |
示例 2:
1 | 输入: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 * 10^4
1 <= words[i].length <= 10
words[i]
由小写英文字母组成words
中的所有字符串互不相同
2. 思路
- 已知题目要求获取的是
board
内所有能够组成words
内任意一个单词的单词集合,也就是说,要获取的是在board
二维数组中,能够找到任意一个单词序列(可以拐弯)存在于words
单词列表中的字符串集合 - 整体思路可以将
words
转化为前缀树,在回溯二维数组board
进行字符串存在判断,如果存在,则记录在结果集中,有关前缀树的实现,可以参考208. 实现Tire(前缀树)进行复习,不同的是需要在Tire
节点中加入word
变量用于后续的取值,word
变量则是当前节点为最终节点时,将当前匹配的字符串赋值给Tire
节点中的word
变量 - 根据题目提示,可以知道
word[i]
中均由小写字母构成,因此前缀树节点Tire
的children
即可初始化为长度为26的数组 - 第一步则是将方法参数的
words
单词列表统一转化为前缀树 - 第二步则是根据前述的前缀树转化,对
board
二维数组进行逐一回溯判断,根据题目要求同一个单元格内的字母在一个单词中不允许被重复使用,因此将在回溯前将对应的单元格加上访问标记,在回溯后去除对应的访问标记(此处利用的是visitRecord
) - 回溯的过程中,如果遇到当前
Tire
节点为最终节点,则直接获取Tire
类中的word
元素,将其添加至结果字符串集合中,同时为了防止重复添加,需要将最终节点标识标记为false
,相当于前缀树的删除操作,此处需要注意的是,当遇到了最终节点,添加到结果集合中后,仍需继续进行深度遍历,因为有可能存在更长的匹配字符串
3. 代码
1 | class Solution { |
4. 复杂度
时间复杂度: 二维数组共有
m * n
个起点,每次能往4个方向搜索,且搜索的长度不会超过10,因此整体的时间复杂度则是O(m * n * 4^10)
空间复杂度:
$$
O(\sum_{i=1}^{words.length - 1} word[i].length * C),其中C为字符集的大小,本题的字符集大小固定为26
$$