LeetCode 720. 词典中最长的单词

60 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第25天,点击查看活动详情

1.描述

720. 词典中最长的单词 - 力扣(LeetCode) (leetcode-cn.com)

给出一个字符串数组 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] 都只包含小写字母。

2.分析

  1. 按字典顺序对words进行排序。从而按层构建trie tree。从而可以在构建阶段就确定哪些字符串的前缀都是words中包含的字符串。
  2. 逐个遍历words,并进行插入。
  3. 全部插入完成以后,直接从字典树对象longestwords上获取首位字符串,就是结果。(因为输入已经按字典顺序排序了。前面的是字典顺序小的)

3.AC代码

function longestWord(words: string[]): string {
  let trieTree = new Trie();
  //为了正确的维护trie的不同节点上的终结状态 需要按字符串长度顺序升序构建trie tree.
  words.sort((a, b) => {
    return a.localeCompare(b);
  });

  for (let i = 0; i < words.length; i++) {
    const curWord = words[i];
    trieTree.insert(curWord);
  }

  if (trieTree.longestwords.length > 0){
    return trieTree.longestwords[0];
  }

  return "";

};

class Trie {
  private root: TrieNode;
  public longestwords: string[] = [];
  constructor(){
    this.root = new TrieNode("/", 0);
  }

  //往trie树中插入一个字符串
  insert(word: string){
    let p:TrieNode = this.root;
    let isEveryCharEndingChar = true;
    for (let i = 0; i < word.length; i++) {
      const char = word[i];
      if (!p.children.has(char)){
        let newNode = new TrieNode(char, p.level + 1);
        p.children.set(char, newNode);
      }
      //@ts-ignore
      p = p.children.get(char);
      if (i === word.length - 1){
        p.isEndingChar = true;
      }
      isEveryCharEndingChar = isEveryCharEndingChar && p.isEndingChar;
    }
    if (isEveryCharEndingChar){
      if (this.longestwords.length === 0){
        this.longestwords.push(word);
      } else if (this.longestwords[0].length < word.length){
        this.longestwords = [word];
      } else if (this.longestwords[0].length === word.length){
        this.longestwords.push(word);
      }
    }
  }
}

class TrieNode {
  data: string = ""
  level: number = -1
  isEndingChar: boolean = false
  children: Map<string, TrieNode>;

  constructor(data: string, level: number){
    this.data = data;
    this.level = level;
    this.children = new Map();
  }
}

4.总结

前缀树免DFS,直接构建过程求解最长单词即可