You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

123 lines
3.3 KiB

2 years ago
package class26;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
// 本题测试链接 : https://leetcode.com/problems/word-search-ii/
public class Code02_WordSearchII {
public static class TrieNode {
public TrieNode[] nexts;
public int pass;
public boolean end;
public TrieNode() {
nexts = new TrieNode[26];
pass = 0;
end = false;
}
}
public static void fillWord(TrieNode head, String word) {
head.pass++;
char[] chs = word.toCharArray();
int index = 0;
TrieNode node = head;
for (int i = 0; i < chs.length; i++) {
index = chs[i] - 'a';
if (node.nexts[index] == null) {
node.nexts[index] = new TrieNode();
}
node = node.nexts[index];
node.pass++;
}
node.end = true;
}
public static String generatePath(LinkedList<Character> path) {
char[] str = new char[path.size()];
int index = 0;
for (Character cha : path) {
str[index++] = cha;
}
return String.valueOf(str);
}
public static List<String> findWords(char[][] board, String[] words) {
TrieNode head = new TrieNode(); // 前缀树最顶端的头
HashSet<String> set = new HashSet<>();
for (String word : words) {
if (!set.contains(word)) {
fillWord(head, word);
set.add(word);
}
}
// 答案
List<String> ans = new ArrayList<>();
// 沿途走过的字符收集起来存在path里
LinkedList<Character> path = new LinkedList<>();
for (int row = 0; row < board.length; row++) {
for (int col = 0; col < board[0].length; col++) {
// 枚举在board中的所有位置
// 每一个位置出发的情况下,答案都收集
process(board, row, col, path, head, ans);
}
}
return ans;
}
// 从board[row][col]位置的字符出发,
// 之前的路径上走过的字符记录在path里
// cur还没有登上有待检查能不能登上去的前缀树的节点
// 如果找到words中的某个str就记录在 res里
// 返回值从row,col 出发一共找到了多少个str
public static int process(
char[][] board, int row, int col,
LinkedList<Character> path, TrieNode cur,
List<String> res) {
char cha = board[row][col];
if (cha == 0) { // 这个row col位置是之前走过的位置
return 0;
}
// (row,col) 不是回头路 cha 有效
int index = cha - 'a';
// 如果没路,或者这条路上最终的字符串之前加入过结果里
if (cur.nexts[index] == null || cur.nexts[index].pass == 0) {
return 0;
}
// 没有走回头路且能登上去
cur = cur.nexts[index];
path.addLast(cha);// 当前位置的字符加到路径里去
int fix = 0; // 从row和col位置出发后续一共搞定了多少答案
// 当我来到row col位置如果决定不往后走了。是不是已经搞定了某个字符串了
if (cur.end) {
res.add(generatePath(path));
cur.end = false;
fix++;
}
// 往上、下、左、右,四个方向尝试
board[row][col] = 0;
if (row > 0) {
fix += process(board, row - 1, col, path, cur, res);
}
if (row < board.length - 1) {
fix += process(board, row + 1, col, path, cur, res);
}
if (col > 0) {
fix += process(board, row, col - 1, path, cur, res);
}
if (col < board[0].length - 1) {
fix += process(board, row, col + 1, path, cur, res);
}
board[row][col] = cha;
path.pollLast();
cur.pass -= fix;
return fix;
}
}