小知识,大挑战!本文正在参与“程序员必备小知识”创作活动
212. 单词搜索 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"] 输出:[]
解题思路
使用前缀树保存单词列表,遍历二维网格的每一个元素,以其为起始节点,使用dfs匹配前缀树
代码
class Solution {
class Trie {
public Node root = new Node();
public Trie() {
}
public void insert(String word) {
Node cur = root;
for (int i = 0; i < word.length(); i++) {
if (cur.nodes[word.charAt(i) - 'a'] == null)
cur.nodes[word.charAt(i) - 'a'] = new Node();
cur = cur.nodes[word.charAt(i) - 'a'];
}
cur.isEnd = true;
}
}
class Node {
Node[] nodes;
boolean isEnd = false;
public Node() {
nodes = new Node[26];
}
}
int[][] d = new int[][]{{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
Set<String> strings = new HashSet<>();
public List<String> findWords(char[][] board, String[] words) {
StringBuilder sb = new StringBuilder();
int n = board.length, m = board[0].length;
boolean[][] ck = new boolean[n][m];
Trie trie = new Trie();
for (String c : words)
trie.insert(c);
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
dfsFindWords(board, i, j, sb, trie.root, ck);
return new ArrayList(strings);
}
public void dfsFindWords(char[][] board, int x, int y, StringBuilder stringBuilder, Node th, boolean[][] check) {
if (th.isEnd) strings.add(stringBuilder.toString());
int cur = board[x][y] - 'a';
if (th.nodes[cur] != null) {
stringBuilder.append(board[x][y]);
check[x][y] = true;
for (int[] dd : d) {
int nx = x + dd[0], ny = y + dd[1];
if (nx < 0 || ny < 0 || nx >= board.length || ny >= board[0].length || check[nx][ny])
continue;
dfsFindWords(board, nx, ny, stringBuilder, th.nodes[cur], check);
}
if (th.nodes[cur].isEnd) strings.add(stringBuilder.toString());
stringBuilder.deleteCharAt(stringBuilder.length() - 1);
check[x][y] = false;
}
}
}