https://leetcode-cn.com/problems/word-search-ii/

回溯 + 剪枝 + 前缀树

利用前缀树的pass来保证不走重复路,不重复收集答案
image.png
image.png

  1. // 前缀树节点
  2. public static class Node{
  3. Node[] nexts;
  4. int pass;
  5. int end;
  6. public Node(){
  7. nexts = new Node[26];
  8. pass = 0;
  9. end = 0;
  10. }
  11. }
  12. public List<String> findWords(char[][] board, String[] words) {
  13. //前缀树最顶端的头
  14. Node root = new Node();
  15. //构建前缀树
  16. for (String word : words) {
  17. Node cur = root;
  18. for (int i = 0; i < word.length(); i++) {
  19. int path = word.charAt(i) - 'a';
  20. if (cur.nexts[path] == null) {
  21. cur.nexts[path] = new Node();
  22. }
  23. cur = cur.nexts[path];
  24. cur.pass++;
  25. }
  26. cur.end++;
  27. }
  28. List<String> ans = new ArrayList<>(); // 答案
  29. // 沿途走过的字符,收集起来存在path里
  30. LinkedList<Character> path = new LinkedList<>();
  31. for (int i = 0; i < board.length; i++) {
  32. for (int j = 0; j < board[0].length; j++) {
  33. // 每个位置出发的情况下,答案都收集
  34. dfs(board, i, j, path, root, ans);
  35. }
  36. }
  37. return ans;
  38. }
  39. /*
  40. * @param path 当前路径
  41. * @param cur 当前前缀树节点
  42. * @param ans 收集答案
  43. * @return 返回收集了几个字符串答案(为了不重复收集答案用)
  44. */
  45. public int dfs(char[][] board, int row, int col, LinkedList<Character> path, Node cur, List<String> ans) {
  46. char c = board[row][col];
  47. if (c == 0) { // 这个位置之前走过,不走回头路
  48. return 0;
  49. }
  50. int index = c - 'a';
  51. /* 剪枝
  52. 1. 前缀树没路可走 2. 从当前位置往下的答案都收集过了,不走重复路,不重复收集*/
  53. if ( cur.nexts[index] == null || cur.nexts[index].pass == 0){
  54. return 0;
  55. }
  56. cur = cur.nexts[index];
  57. path.add(c);
  58. int count = 0; //收集了多少个答案
  59. if (cur.end > 0) {
  60. char[] str = new char[path.size()];
  61. int i = 0;
  62. for (char p : path) {
  63. str[i++] = p;
  64. }
  65. ans.add(String.valueOf(str));
  66. cur.end--; // 防止重复收集答案
  67. count++;
  68. }
  69. // 增加现场, 不走回头路机制
  70. board[row][col] = 0;
  71. if (row > 0) {
  72. count += dfs(board, row - 1, col, path, cur, ans);
  73. }
  74. if (row < board.length - 1) {
  75. count += dfs(board, row + 1, col, path, cur, ans);
  76. }
  77. if (col > 0) {
  78. count += dfs(board, row, col - 1, path, cur, ans);
  79. }
  80. if (col < board[0].length - 1) {
  81. count += dfs(board, row, col + 1, path, cur, ans);
  82. }
  83. // 恢复现场
  84. board[row][col] = c;
  85. // 恢复现场
  86. path.pollLast();
  87. cur.pass -= count;
  88. return count;
  89. }