leetcode 127. 单词接龙 (BFS双端搜索,字符串哈希降低复杂度)

题目:

leetcode 127. 单词接龙 https://leetcode-cn.com/problems/word-ladder/

题目大意:

给定两个单词(起始单词和终止单词)和一个词典,每次转化只能改变单词的某一个字母,求从起始单词转化到终止单词所需要的最小次数。

思路:

  1. 如何从一个单词改变到下一个搜索的单词:
    如果每次从词典中两两匹配,那么需要的复杂度是:O(N^2*M)(其中N为词典中的单词总数,M为每个单词的长度)
    如果采用字符串hash,每次改变单词字符的状态(单个字符最多26种状态),那么需要的复杂度为:O(N*26*M),可以很大程度的降低复杂度

  2. 题目中求最小的转换的次数,显然采用BFS。那如何降低BFS搜索的复杂度:
    注意到每个单词是相互独立的,也就是我们从起始单词往终止单词搜索,与从终止单词往起始单词搜索的结果是等价的,这样我们可以采用双端搜索。每轮交替搜索起始或者终止单词的下一个状态,边搜索边标记,直到两者相遇或者中间过程结束。

class Solution {
public:
    //好题: 学习BFS双端搜索
    
    //注意wordlist里面可能出现自环
    //怎么判断两个字符串 仅仅相差一个字母
    //预处理?hash 判断
    //把判断的复杂度从O(N^2) 降到O(26*N)
    int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
        if(beginWord==endWord) return 2;
        // unordered_set<string> word(wordList);
        unordered_set<string> word(wordList.begin(),wordList.end());
        //判断末尾词是否在word 里面
        if(!word.count(endWord)) return 0;

        unordered_set<string> s1={beginWord},s2={endWord},vis;
        int num=0;
        //结束条件
        //双边搜索,交替搜索
        while(!s1.empty() && !s2.empty()){
            num++;
            if(s1.size()>s2.size()){
                unordered_set<string> t=s1;
                s1=s2;
                s2=t;
            }//交替搜索
            
            unordered_set<string> tmp; 
            for(string cur:s1){
                for(int i=0;i<cur.size();i++){
                    
                    char old=cur[i];

                    for(int j=0;j<26;j++){
                        cur[i]='a'+j;

                        if(s2.count(cur)){
                            return num+1;
                        }
                        if(!vis.count(cur) && word.count(cur)){
                            tmp.insert(cur);
                            vis.insert(cur);
                        }
                    }
                    cur[i]=old;//保证每次只改变一位字符的状态
                }
            }

            s1=tmp;//下一个搜索的状态
        }

        return 0;

    }
};

参考思路:
https://leetcode.com/problems/word-ladder/discuss/40711/Two-end-BFS-in-Java-31ms.

posted @ 2021-01-23 20:12  xzhws  阅读(102)  评论(0编辑  收藏  举报