[LeetCode][720] Longest Word in Dictionary

[LeetCode][720] Longest Word in Dictionary题解


标签:tire / hash / 剪枝

题意:找到最长的单词,该单词要在数组中拥有一个前缀,满足该前缀也是在数组中。如果有相同长度返回字典序小的。也就是返回最长的字典序最小的字符串。

这里我们使用了前缀树数据结构。
首先对数组进行排序,排序规则为长的在前面,如果相同长度,字典序小的在前面。
对于一组字符串,把遍历加入到前缀树中。
然后,对排序过后的vector<string>数组进行遍历,如果找到一个单词在前缀树中有前缀则返回该单词。

核心代码:

bool startsWith(string prefix)
    {
        TrieNode *p = root;
        for (auto &a : prefix)
        {
            int i = a - 'a';
            if (!p->child[i])
            {
                return false;
            }
            p = p->child[i];
            if (!p->isWord)
            {
                return false;
            }
        }
        //如果是加入了单词则需要判断是不是被标记为isword
        //这里是找是不是前缀因此不需要标记isword
        return true;
    }

思路参考自:https://zxi.mytechroad.com/blog/string/leetcode-720-longest-word-in-dictionary/

AC代码

/*
 * [720] Longest Word in Dictionary
 *
 * https://leetcode.com/problems/longest-word-in-dictionary/description/
 *
 * algorithms
 * Easy (42.29%)
 * Total Accepted:    23.7K
 * Total Submissions: 56K
 * Testcase Example:  '["w","wo","wor","worl","world"]'
 *
 * Given a list of strings words representing an English Dictionary, find the
 * longest word in words that can be built one character at a time by other
 * words in words.  If there is more than one possible answer, return the
 * longest word with the smallest lexicographical order.  If there is no
 * answer, return the empty string.
 *
 * Example 1:
 *
 * Input:
 * words = ["w","wo","wor","worl", "world"]
 * Output: "world"
 * Explanation:
 * The word "world" can be built one character at a time by "w", "wo", "wor",
 * and "worl".
 *
 *
 *
 * Example 2:
 *
 * Input:
 * words = ["a", "banana", "app", "appl", "ap", "apply", "apple"]
 * Output: "apple"
 * Explanation:
 * Both "apply" and "apple" can be built from other words in the dictionary.
 * However, "apple" is lexicographically smaller than "apply".
 *
 *
 *
 * Note:
 * All the strings in the input will only contain lowercase letters.
 * The length of words will be in the range [1, 1000].
 * The length of words[i] will be in the range [1, 30].
 *
 */
class TrieNode
{
  public:
    TrieNode *child[26];
    bool isWord;
    TrieNode() : isWord(false)
    {
        for (auto &a : child)
        {
            a = NULL;
        }
    }
};
class Trie
{
  private:
    TrieNode *root;

  public:
    // 1、对每个结点开一个字母集大小的数组,对应的下标是儿子所表示的字母,
    // 内容则是这个儿子对应在大数组上的位置,即标号;

    // 2、对每个结点挂一个链表,按一定顺序记录每个儿子是谁;

    // 3、使用左儿子右兄弟表示法记录这棵树。
    /** Initialize your data structure here. */

    Trie()
    {
        root = new TrieNode();
    }

    /** Inserts a word into the trie. */
    void insert(string word)
    {
        TrieNode *p = root;
        for (auto &a : word)
        {
            int i = a - 'a';
            if (!p->child[i])
            {
                p->child[i] = new TrieNode();
            }
            p = p->child[i];
        }
        //退出时候已经达到树的末尾
        p->isWord = true;
    }

    /** Returns if the word is in the trie. */
    bool search(string word)
    {
        TrieNode *p = root;
        for (auto &a : word)
        {
            int i = a - 'a';
            if (!p->child[i])
            {
                return false;
            }
            p = p->child[i];
        }
        return p->isWord;
    }

    /** Returns if there is any word in the trie that starts with the given prefix. */
    bool startsWith(string prefix)
    {
        TrieNode *p = root;
        for (auto &a : prefix)
        {
            int i = a - 'a';
            if (!p->child[i])
            {
                return false;
            }
            p = p->child[i];
            if (!p->isWord)
            {
                return false;
            }
        }
        //如果是加入了单词则需要判断是不是被标记为isword
        //这里是找是不是前缀因此不需要标记isword
        return true;
    }
};

class Solution
{
  public:
    string longestWord(vector<string> &words)
    {
        std::sort(words.begin(), words.end(),
                  [](const string &w1, const string &w2) {
                      if (w1.length() != w2.length())
                          return w1.length() > w2.length();
                      return w1 < w2;
                  });
        Trie trie;
        for (const string &word : words)
        {
            trie.insert(word);
        }

        for (const string &word : words)
        {
            if (trie.startsWith(word))
            {
                return word;
            }
        }
        return "";
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值