[LeetCode]Word Ladder

解题思路:
双向 宽度搜索
1,BFS的基本思想是为了找到最短路径,这里为了提高搜索效率,采用双向搜索。
2,是从beginWord方向寻找next level,还是从endWord方向寻找next level,取决于哪个方向要找寻的点少
数据结构:
1,unordered_set : unusedWords, wordDict中所有未被visit的words
2,unordered_set : activeWords[startSet], 保存我们即将要用于搜索的words(beginWord 方向,或者endWord方向,取决于size)
3,unordered_set : activeWords[endSet], 与2中 unordered_set 对应的另一边words
如果BFS扩展路径的时候(从activeWords[startSet])到达了一个存在于(activeWords[endSet])的word,那么我们就找到了一个条最短路径
4,unordered_set :  activeWords[nextSet],保存BFS从activeWords[StartSet] 扩展出的节点word
5,对BFS的每一步,我们动态的决定应该从哪个方向扩展,主要取决于哪个方向的nodes更少。这样做可以降低搜索复杂度。

在BFS阶段,遍历startSet里面的每一个word,先看endSet里有没有next Level的单词,如果有,则找到一条最短路径,直接返回。否则,再在unusedSet里面找next Level的节点,如果有,加入nextSet,并且从unusedWords中删除 

// 860 ms
class Solution {
public:
    int ladderLength(string beginWord, string endWord, unordered_set<string>& wordDict) {
        int bLen = beginWord.length();
        int eLen = endWord.length();
        int size = wordDict.size();
        if (bLen != eLen || bLen == 0 || size == 0) return 0;

        unordered_set<string> unusedWords = wordDict; // words that never visited before
        unordered_set<string> activeWords[3];
        int startSet = 0;
        int endSet = 1;
        int nextSet = 2;
        int depth = 2;

        activeWords[startSet].insert(beginWord);
        activeWords[endSet].insert(endWord);
        unusedWords.erase(beginWord);
        unusedWords.erase(endWord);
        while(!activeWords[startSet].empty()){
            for (auto it : activeWords[startSet]){
                for (auto itend : activeWords[endSet]){
                    if (match(it, itend)){
                        return depth;
                    }
                }

                vector<string> temp;
                for (auto itun : unusedWords){
                    if (match(it, itun)){
                        activeWords[nextSet].insert(itun);
                        temp.push_back(itun);
                        //这里不能直接用下面这句,因为你迭代器是 unusedWords的,把它的元素删除,迭代器就被玩坏了
                        //unusedWords.erase(itun);
                    }
                }
                for (auto istr : temp){
                    unusedWords.erase(istr);
                }

            }
            depth++;
            swap(startSet, nextSet);
            if (activeWords[startSet].size() > activeWords[endSet].size()) {
                swap(startSet, endSet);
            }
            activeWords[nextSet].clear();
        }
        return 0;
    }

    bool match(string wordA, string wordB){
        if (wordA.length() != wordB.length()) return false;
        int diff = 0;
        for (int i = 0; i < wordA.length(); ++i){
            if (wordA[i] == wordB[i]) continue;

            diff++;
            if (diff > 1){
                return false;
            }
        }
        if (diff == 1) return true;
        return false;
    }
};


上述算法860ms,改变一下match算法,时间减少的68ms,原因在于
第一种算法,每两个word都要进行一次匹配,O(m*n), 每次匹配要判断 word的长度个次数,所以总时间复杂度时O(m*n*k)
第二种算法,由于unordered_set的查找时间复杂度为O(1), 所以实际的时间复杂度是只跟word的长度有关系,即O(n), 26个字母的替换,常量啦 
        for (auto it : activeWords[startSet]){
                char temp, i;
                for(int i = 0; i < it.length(); ++i){
                    temp = it[i];
                    for(char j = 'a'; j < 'z'; ++j){
                        if (temp == j) continue;
                        it[i] = j;
                        if (activeWords[endSet].count(it) > 0){
                            return depth;
                        }else if (unusedWords.count(it) > 0){
                            activeWords[nextSet].insert(it);
                            unusedWords.erase(it);
                        }
                    }
                    it[i] = temp;
                }
            }




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值