玩命加载中 . . .

720-词典中最长的单词


LeetCode 720. 词典中最长的单词

给出一个字符串数组 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" 

method 1: 哈希表

排序:如果长度相同,按字典序拍,否则长的排前面,这样第一个满足条件的就是结果

字典存哈希表中,遍历字符串的每个子串看在不在哈希表中

static bool cmp(const string& a, const string& b) {
    if (a.size() == b.size()) return a < b;
    return a.size() > b.size();
}
unordered_set<string> st;
bool dfs(string& s) {
    for (int i = 1; i < s.size(); i++) {
        if (st.count(s.substr(0, i)) == 0) return false;
    }
    return true;
}
string longestWord(vector<string>& words) {
    for (auto w : words) st.insert(w);
    sort(words.begin(), words.end(), cmp);
    for (auto word : words) {
        if (dfs(word)) {
            return word;
        }
    }
    return "";
}

也可以不排序

string longestWord(vector<string>& words) {
    for (auto w : words) st.insert(w);
    string res;
    for (auto word : words) {
        if (word.size() < res.size() || (word.size() == res.size() && word > res)) continue;	// 剪枝
        if (dfs(word)) res = word;
    }
    return res;
}

method 2: Trie树

Trie树可以方便得查找一个字符串的所有子串是否在字典中

如果某个前缀的isEnd=false,说明字典中没有这个前缀单词,直接返回

class Trie {
public:
    vector<Trie*> next;
    bool isEnd;
    Trie(): next(26), isEnd(false) {}
    void insert(string s) {
        Trie *root = this;
        for (auto c : s) {
            if (!root->next[c - 'a']) {
                root->next[c - 'a'] = new Trie();
            }
            root = root->next[c - 'a'];
        }
        root->isEnd = true;
    }
    bool search(string s) {
        Trie *root = this;
        for (auto c : s) {
            if (!root->next[c - 'a'] || !root->next[c - 'a']->isEnd) return false;
            root = root->next[c - 'a'];
        }
        return true;
    }
};
class Solution {
public:
    string longestWord(vector<string>& words) {
        Trie trie;
        for (auto w : words) trie.insert(w);
        string res;
        for (auto word : words) {
            if (word.size() < res.size() || (word.size() == res.size() && word > res)) continue;
            if (trie.search(word)) {
                res = word;
            }
        }
        return res;
    }
};

面试题 17.15. 最长单词

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

示例:

输入: ["cat","banana","dog","nana","walk","walker","dogwalker"]
输出: "dogwalker"
解释: "dogwalker"可由"dog""walker"组成。

method

跟上题不同的是,这里换成字符串要由字典中的单词组成,而且不能是自己,所以用排序,然后把自己移除

DFS找分割每个子串是否可以找到对应单词

static bool cmp(const string& a, const string& b) {
    if (a.size() == b.size()) return a < b;
    return a.size() > b.size();
}
unordered_set<string> st;
bool dfs(string s) {
    if (st.count(s)) return true;
    for (int i = 1; i <= s.size(); i++) {
        if (st.count(s.substr(0, i))) {	// 找从0开始的子串,如果s[0:i)可以,就递归找剩下的s[i:n-1]
            if (dfs(s.substr(i))) return true;
        }
    }
    return false;
}
string longestWord(vector<string>& words) {
    for (auto w : words) st.insert(w);
    sort(words.begin(), words.end(), cmp);
    for (auto word : words) {
        st.erase(word);	// 移除,不然会找到自己
        if (dfs(word)) {
            return word;
        }
    }
    return "";
}

文章作者: kunpeng
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 kunpeng !
  目录