1. 程式人生 > >Crack LeetCode 之 127. Word Ladder

Crack LeetCode 之 127. Word Ladder

https://leetcode.com/problems/word-ladder/

本文的解釋部分來自於連結,出於學習目的我租了部分整理和修改:https://blog.csdn.net/linhuanmars/article/details/23029973

本題的本質是圖,圖的頂點則是每個字串。因為每次只能改一個字元,所以該字串的每個字元可能對應的邊有25個(26個小寫字母減去自己),那麼一個字串可能存在的邊是25*L條。接下來我們再檢查這些邊對應的字串是否在字典裡,以此類推就可以得到一個完整的圖的結構。根據題目的要求,等價於求這個圖一個頂點到另一個頂點的最短路徑,我們用廣度優先搜尋即可。
該演算法中最差情況是把所有長度為L的字串都掃描一遍,或者把字典中的字串都掃描一遍,而長度為L的字串共有26^L,所以時間複雜度是O(min(26^L, size(dict)),空間上需要儲存訪問情況,也是O(min(26^L, size(dict))。C++程式碼如下:

class Solution
{
public:
    int ladderLength(string start, string end, vector<string>& wordList)
    {
        if(start.empty() || end.empty() || start.length()!=end.length())
            return 0;

        list<string> strlist;
        set<string> visited;
        set<string> dic;
        int level= 1;
        int lastNum = 1;
        int curNum = 0;
        strlist.push_back(start);
        visited.insert(start);
        
        for (vector<string>::iterator ite = wordList.begin(); ite!=wordList.end(); ++ite)
            dic.insert(*ite);

        while(strlist.empty() == false) {
            string cur = strlist.front();
            strlist.pop_front();
            lastNum--;

            for(int i=0;i<cur.length();i++) {
                string charCur = cur;

                for(char c='a';c<='z';c++) {
                    charCur[i] = c;

                    if( dic.find(charCur)!=dic.end() && visited.find(charCur)==visited.end()) {
                        if(charCur == end)
                            return level+1;

                        curNum++;
                        strlist.push_back(charCur);
                        visited.insert(charCur);
                    }
                }
            }

            if(lastNum==0) {
                lastNum = curNum;
                curNum = 0;
                level++;
            }
        }

        return 0;
    }
};

Python程式碼如下:

class Solution:
    def ladderLength(self, beginWord, endWord, wordList):
        if not beginWord or not endWord or not wordList:
            return 0;

        wordSet = set()
        for word in wordList:
            wordSet.add(word)

        level = 1
        processedSet = set()
        curList = [beginWord]

        while True:
            level = level + 1
            nextList = []

            for curWord in curList:
                if curWord in processedSet:
                    continue

                for i in range(len(curWord)):
                    part1 = curWord[:i]; part2 = curWord[i+1:]

                    for j in 'abcdefghijklmnopqrstuvwxyz':
                        nextword = part1 + j + part2

                        if nextword == curWord:
                            continue

                        if nextword not in wordSet:
                            continue

                        if nextword == endWord:
                            return level

                        nextList.append(nextword)

                processedSet.add(curWord)

            if not nextList:
                return 0

            curList = nextList

        return 0