127. Word Ladder

问题

Given two words (beginWord and endWord), and a dictionary's word list, find the length of shortest transformation sequence from beginWord to endWord, such that:

  1. Only one letter can be changed at a time.
  2. Each transformed word must exist in the word list. Note that beginWord is not a transformed word.

Note:

  • Return 0 if there is no such transformation sequence.
  • All words have the same length.
  • All words contain only lowercase alphabetic characters.
  • You may assume no duplicates in the word list.
  • You may assume beginWord and endWord are non-empty and are not the same.

UPDATE (2017/1/20):
The wordList parameter had been changed to a list of strings (instead of a set of strings). Please reload the code definition to get the latest changes.

例子

Given:
beginWord = "hit"
endWord = "cog"
wordList = ["hot","dot","dog","lot","log","cog"]
As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
return its length 5.

分析

注意到每个相邻的单词都只有一个字母的差异。我们可以使用bfs解决这个问题:从beginWord出发,每一层的单词都和上一个单词有一个字母的差别,不断搜索,直到搜索到endWord。

要点

用two-side bfs算法可以加速O(logN/2)^M,N为单词表个数,M为bfs树节点的平均度数。因为two-side bfs依次从beginWord和endWord开始遍历,可以有效减少遍历的次数。

时间复杂度

O(n)

空间复杂度

O(n)

代码

bfs

class Solution {
public:
    int ladderLength(string beginWord, string endWord, vector& wordList) {
        // unordered_set可以提高查找效率O(1)
        unordered_set wordSet(wordList.begin(), wordList.end());

        queue wordQueue;
        transform(beginWord, wordSet, wordQueue);

        int count = 2;
        while (!wordQueue.empty()) {
            int num = wordQueue.size();
            for (int i = 0; i < num; i++) {
                string word = wordQueue.front();
                wordQueue.pop();
                if (word == endWord) return count;
                transform(word, wordSet, wordQueue);
            }
            count++;
        }

        return 0;
    }

private:
    // 找出所有和word有一个字母不同的单词,从单词表里删除,并且添加到队列中
    void transform(string word, unordered_set &wordSet, queue &wordQueue) {
        for (int i = 0; i < word.size(); i++) {
            char letter = word[i];
            for (int j = 0; j < 26; j++) {
                word[i] = 'a' + j;
                if (wordSet.find(word) == wordSet.end()) continue;

                wordQueue.push(word);
                wordSet.erase(word);
            }
            word[i] = letter;
        }
    }
};

two-side bfs

class Solution {
public:
    int ladderLength(string beginWord, string endWord, vector& wordList) {
        unordered_set wordSet(wordList.begin(), wordList.end());
        if (wordSet.find(endWord) == wordSet.end()) return 0;
        
        wordSet.erase(beginWord);
        wordSet.erase(endWord);
        unordered_set beginSet, endSet, *p1, *p2;
        beginSet.insert(beginWord);
        endSet.insert(endWord);
        p1 = &beginSet;
        p2 = &endSet;

        int ladder = 2;
        while (!p1->empty() && !p2->empty())
        {
            // 保持p1的大小小于p2,提高遍历效率
            if (p1->size() > p2->size())
                swap(p1, p2);

            unordered_set tempSet;
            for (string word : *p1) {
                for (int i = 0; i < word.size(); i++) {
                    char letter = word[i];
                    for (int j = 0; j < 26; j++) {
                        word[i] = 'a' + j;
                        if (p2->find(word) != p2->end())
                            return ladder;
                        if (wordSet.find(word) != wordSet.end()) {
                            wordSet.erase(word);
                            tempSet.insert(word);
                        }
                    }
                    word[i] = letter;
                }
            }
            swap(*p1, tempSet);
            ladder++;
        }
        return 0;
    }
};

你可能感兴趣的:(127. Word Ladder)