[LeetCode] Longest Word in Dictionary 字典中的最長單詞


 

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].

 

這道題給了我們一個字典,是個字符串數組,然后問我們從單個字符開始拼,最長能組成啥單詞,注意中間生成的字符串也要在字典中存在,而且當組成的單詞長度相等時,返回字母順序小的那個。好,看到這么多前綴一樣多字符串,是不是很容易想到用前綴樹來做,其實我們並不需要真正的建立前綴樹結點,可以借鑒查找的思想來做。那么為了快速的查找某個單詞是否在字典中存在,我們將所有單詞放到哈希集合中,在查找的時候,可以采用BFS或者DFS都行。先來看BFS的做法,使用一個queue來輔助,我們先把所有長度為1的單詞找出排入queue中,當作種子選手,然后我們進行循環,每次從隊首取一個元素出來,如果其長度大於我們維護的最大值mxLen,則更新mxLen和結果res,如果正好相等,也要更新結果res,取字母順序小的那個。然后我們試着增加長度,做法就是遍歷26個字母,將每個字母都加到單詞后面,然后看是否在字典中存在,存在的話,就加入queue中等待下一次遍歷,完了以后記得要恢復狀態,參見代碼如下:

 

解法一:

class Solution {
public:
    string longestWord(vector<string>& words) {
        string res = "";
        int mxLen = 0;
        unordered_set<string> s(words.begin(), words.end());
        queue<string> q;
        for (string word : words) {
            if (word.size() == 1) q.push(word);
        }
        while (!q.empty()) {
            string t = q.front(); q.pop();
            if (t.size() > mxLen) {
                mxLen = t.size();
                res = t;
            } else if (t.size() == mxLen) {
                res = min(res, t);
            }
            for (char c = 'a'; c <= 'z'; ++c) {
                t.push_back(c);
                if (s.count(t)) q.push(t);
                t.pop_back();
            }
        }
        return res;
    }
};

 

下面來看遞歸的解法,前面都一樣,不同在於直接對長度為1的單詞調用遞歸函數,在遞歸中,還是先判斷單詞和mxLen關系來更新結果res,然后就是遍歷所有字符,加到單詞后面,如果在集合中存在,調用遞歸函數,結束后恢復狀態,參見代碼如下:

 

解法二:

class Solution {
public:
    string longestWord(vector<string>& words) {
        string res = "";
        int mxLen = 0;
        unordered_set<string> s(words.begin(), words.end());for (string word : words) {
            if (word.size() == 1) helper(s, word, mxLen, res);
        }
        return res;
    }
    void helper(unordered_set<string>& s, string word, int& mxLen, string& res) {
        if (word.size() > mxLen) {
            mxLen = word.size();
            res = word;
        } else if (word.size() == mxLen) {
            res = min(res, word);
        }
        for (char c = 'a'; c <= 'z'; ++c) {
            word.push_back(c);
            if (s.count(word)) helper(s, word, mxLen, res);
            word.pop_back();
        }
    }
};

 

下面這種解法是論壇上的高分解法,其實我們只要給數組排個序,就可以使用貪婪算法來做了,並不需要什么DFS或BFS這么復雜。首先建立一個空的哈希set,然后我們直接遍歷排序后的字典,對於當前的單詞,如果當前單詞長度為1,或者該單詞去掉最后一個字母后在集合中存在,這也不難理解,長度為1,說明是起始單詞,不需要的多余的判斷,否則的話就要判斷其去掉最后一個字母后的單詞是否在集合中存在,存在的話,才說明其中間單詞都存在,因為此時是從短單詞向長單詞遍歷,只要符合要求的才會加入集合,所以一旦其去掉尾字母的單詞存在的話,那么其之前所有的中間情況都會在集合中存在。我們更新結果res時,要判斷當前單詞長度是否大於結果res的長度,因為排序過后,默認先更新的字母順序小的單詞,所有只有當當前單詞長度大,才更新結果res,之后別忘了把當前單詞加入集合中,參見代碼如下:

 

解法三:

class Solution {
public:
    string longestWord(vector<string>& words) {
        string res = "";
        unordered_set<string> s;
        sort(words.begin(), words.end());
        for (string word : words) {
            if (word.size() == 1 || s.count(word.substr(0, word.size() - 1))) {
                res = (word.size() > res.size()) ? word : res;
                s.insert(word);
            }
        }
        return res;
    }
};

 

類似題目:

Longest Word in Dictionary through Deleting

Implement Magic Dictionary

 

參考資料:

https://discuss.leetcode.com/topic/109643/java-c-clean-code

 

LeetCode All in One 題目講解匯總(持續更新中...)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM