LeetCode_前缀树_排序_哈希集合_中等_720.词典中最长的单词

Love The Way You Lie 2024-04-07 13:21 136阅读 0赞

目录

  • 1.题目
  • 2.思路
  • 3.代码实现(Java)

1.题目

给出一个字符串数组 words 组成的一本英语词典。返回 words 中最长的一个单词,该单词是由 words 词典中其他单词逐步添加一个字母组成。若其中有多个可行的答案,则返回答案中字典序最小的单词。若无答案,则返回空字符串。

示例 1:
输入:words = [“w”,“wo”,“wor”,“worl”, “world”]
输出:“world”
解释: 单词”world”可由”w”, “wo”, “wor”, 和 “worl”逐步添加一个字母组成。

示例 2:
输入:words = [“a”, “banana”, “app”, “appl”, “ap”, “apply”, “apple”]
输出:“apple”
解释:“apply” 和 “apple” 都能由词典中的单词组成。但是 “apple” 的字典序小于 “apply”

提示:
1 <= words.length <= 1000
1 <= words[i].length <= 30
所有输入的字符串 words[i] 都只包含小写字母。

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/longest-word-in-dictionary

2.思路

(1)排序 & 哈希集合
思路参考本题官方题解。

① 先对数组 words 进行排序,排序规则如下:
1)首先按照单词长度进行升序排序;
2)如果单词长度相同,则按照字典序降序排序;

② 定义哈希集合 hashSet,并将空串 (“”) 加入其中,然后再开始遍历数组 words,假设 words[i] = “worl”,判断当前单词去掉最后一个字母的前缀(即”wor”)是否存在于 hashSet 中:
1)如果存在,则说明 hashSet 一定还包含 “w”、“wo”,此时的 “worl” 有可能是最终答案,用 res 保存起来。
2)如果不存在,则说明该单词一定不满足题目要求,不予考虑即可。

③ 这里需要注意的是,由于在之前的排序过程中,如果单词长度相同,则按照字典序降序排序,这样就保证了如果同时存在多个答案,在遍历数组 words 的过程中,字典序最小的答案在靠后的位置,所以 res 保存的就是多个可行答案中字典序最小的单词!

(2)前缀树
思路参考本题官方题解。

有关前缀树的具体细节,可以参考208. 实现 Trie (前缀树)这篇文章。

3.代码实现(Java)

  1. //思路1————排序 & 哈希集合
  2. class Solution {
  3. public String longestWord(String[] words) {
  4. String res = "";
  5. int length = words.length;
  6. /*
  7. 将数组 words 进行排序,排序规则如下:
  8. (1) 首先按照单词长度进行升序排序;
  9. (2) 如果单词长度相同,则按照字典序降序排序
  10. */
  11. Arrays.sort(words, (word1, word2) -> {
  12. //返回值为正数,则交换 word1 和 word2
  13. if (word1.length() != word2.length()) {
  14. return word1.length() - word2.length();
  15. } else {
  16. return word2.compareTo(word1);
  17. }
  18. });
  19. Set<String> hashSet = new HashSet<>();
  20. candidates.add("");
  21. for (int i = 0; i < length; i++) {
  22. String word = words[i];
  23. /*
  24. 假设 words[i] = "worl"
  25. 判断当前单词去掉最后一个字母的前缀(即"wor")是否存在于 hashSet 中
  26. (1) 如果存在,则说明 hashSet 一定还包含 "w"、"wo",此时的 "worl" 有可能是最终答案,用 res 保存起来。
  27. (2) 如果不存在,则说明该单词一定不满足题目要求,不予考虑即可。
  28. */
  29. if (hashSet.contains(word.substring(0, word.length() - 1))) {
  30. hashSet.add(word);
  31. //更新 res
  32. res = word;
  33. }
  34. }
  35. return res;
  36. }
  37. }
  38. //思路2————前缀树
  39. class Solution {
  40. public String longestWord(String[] words) {
  41. String res = "";
  42. Trie trie = new Trie();
  43. //将数组 words 中的所有单词插入到前缀树中
  44. for (String word : words) {
  45. trie.insert(word);
  46. }
  47. for (String word : words) {
  48. if (trie.search(word)) {
  49. /*
  50. 更新 res 的条件:
  51. (1) 当前 word 的长度大于 res 的长度;
  52. (2) 或者当前 word 的长度等于 res 的长度,但是 word 的字典序小于 res。
  53. */
  54. if (word.length() > res.length() || (word.length() == res.length() && word.compareTo(res) < 0)) {
  55. //更新 res
  56. res = word;
  57. }
  58. }
  59. }
  60. return res;
  61. }
  62. }
  63. class Trie {
  64. private Trie[] children;
  65. private boolean isEnd;
  66. public Trie() {
  67. //每个节点最多有 26 个子节点,分别对应 26 个小写英文字母
  68. children = new Trie[26];
  69. isEnd = false;
  70. }
  71. //插入字符串
  72. public void insert(String word) {
  73. Trie node = this;
  74. for (int i = 0; i < word.length(); i++) {
  75. char ch = word.charAt(i);
  76. int index = ch - 'a';
  77. if (node.children[index] == null) {
  78. node.children[index] = new Trie();
  79. }
  80. node = node.children[index];
  81. }
  82. node.isEnd = true;
  83. }
  84. public boolean search(String word) {
  85. Trie node = this;
  86. for (int i = 0; i < word.length(); i++) {
  87. char ch = word.charAt(i);
  88. int index = ch - 'a';
  89. if (node.children[index] == null || !node.children[index].isEnd) {
  90. return false;
  91. }
  92. node = node.children[index];
  93. }
  94. return node != null && node.isEnd;
  95. }
  96. }

发表评论

表情:
评论列表 (有 0 条评论,136人围观)

还没有评论,来说两句吧...

相关阅读

    相关 720. 词典单词

    给出一个字符串数组`words`组成的一本英语词典。从中找出最长的一个单词,该单词是由`words`词典中其他单词逐步添加一个字母组成。若其中有多个可行的答案,则返回答案中字典