力扣:17.15. 最长单词

267 阅读1分钟

「这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战

描述

给定一组单词words,编写一个程序,找出其中的最长单词,且该单词由这组单词中的其他单词组合而成。若有多个长度相同的结果,返回其中字典序最小的一项,若没有符合要求的单词则返回空字符串。

  • 示例 1:
输入: ["cat","banana","dog","nana","walk","walker","dogwalker"]
输出: "dogwalker"
解释: "dogwalker"可由"dog""walker"组成。
  • 提示:
  • 0 <= len(words) <= 200
  • 1 <= len(words[i]) <= 100

解析

长度逆序+字典顺序对输入的数组排序(优先检查长度)。使用一个哈希集合得到输入词的集合。

利用DFS来检查某一个词语s是否符合条件:

  • s[0,i) 在集合中出现了
  • s[i, s.length()) 依然符合条件

需要注意的是,为了防止整个词包含但不是拼接结果也返回true,需要在检查之前将这个词本身从集合里面删去。

class Solution {
    public String longestWord(String[] words) {
        Arrays.sort(words, (a, b) -> {
            return (a.length() == b.length()) ? a.compareTo(b) : b.length() - a.length();
        });
        Set<String> dict = new HashSet<>();
        for (String str : words) {
            dict.add(str);
        }
        for (String s : words) {
            dict.remove(s);
            if (dfs(s, dict)) return s;
        }
        return "";
    }
    
    public boolean dfs(String s, Set<String> dict) {
        if (s.length() == 0)
            return true;
        for (int i = 1; i <= s.length(); i++) {
            if (dict.contains(s.substring(0, i)) && dfs(s.substring(i), dict))
                return true;
        }
        return false;
    }
}

此外还有字典树的解题方式:

1.先把所有单词插入树中; 2.按长度降序排序 3.从最长的完整单词开始在字典树中回溯搜索,一旦发现某个字符是单词的结尾,就截取以此为头的子串,在trie中从头递归搜索子串是否为一个单词,如果是可以结束对该完整的单词的判断,并按字典序决定是否作记录;如果不是,继续对该完整单词的字符搜索; 4.因为要求的是最长的,如果下一个要搜索的完整单词已经比记录的单词短了,停止搜索。

运行结果:

执行结果:通过

执行用时:4 ms, 在所有 Java 提交中击败了86.42%的用户

内存消耗:38.2 MB, 在所有 Java 提交中击败了37.75%的用户