LeetCode之Word Ladder

Given two words (beginWord and endWord), and a dictionary, 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 intermediate word must exist in the dictionary

For example,

Given:
start = "hit"
end = "cog"
dict = ["hot","dot","dog","lot","log"]

As one shortest transformation is "hit" -> "hot" -> "dot" -> "dog" -> "cog",
return its length 5.

Note:

  • Return 0 if there is no such transformation sequence.
  • All words have the same length.
  • All words contain only lowercase alphabetic characters.

给定任意两个单词,从一个单词(beginword)开始,每次变化一个字母,问最少需要多少次才能变化到另外一个单词(endword)。


思路很简单,从beginword开始,遍历unordered_map<string> dict ,在里面找到与beginword相差1的单词,将该单词加入队列

每次取队列头结点,对该节点中的单词,如果单词和endword相差1,则返回该节点的层数+1,

否则,在dict中找到与该节点的单词相差1的单词,并且这个单词没有加入到队列过,然后将单词加入队列。


这种方法很直观,小数据量会很快得出结果,但是在大数据量时会非常慢。12K的数据量,跑了5,6秒,简直不能忍。

刚开始以为是入队出队造成字符串频繁拷贝的开销,于是在这个地方进行优化,搞了半天没效果。


于是输出了一下遍历dict元素的次数,发现12K的数据,遍历的次数有1000多万次,难怪会超时。


换个思路,每次把beginword变化一个单词,总共可以变化成多少种?

对于字符串“a”,有25种,对于字符串“ab”,有多少种呢?一直以为是25*25种,后来一想是25*strlen("ab"),共50种

这样,只需要遍历50次,相比遍历整个dict(1万多次),效率实在高太多了。

完整AC代码:

class node{
public:
    const string str;
    int level;
    node(const string& s, int lev):str(s), level(lev){}
};


bool isDiffByOne(const string& s, const string& t)
{
    int count = 0;
    for(unsigned int i = 0;i<s.size();i++){
        if(s[i] != t[i]){
            count++;
        }
        if(count >= 2){
            return false;
        }
    }
    return true;
}


class Solution {
public:
    void foreach(node& nd, queue<node>& q,
                 unordered_set<string>& wordDict,
                 unordered_set<string>& hasvisited)
    {
        for(int i = 0;i<nd.str.size();i++){
            for(int j = 0;j < 26;j++){
                string tmp = nd.str;
                tmp[i] = 'a' + j;
                if(tmp != nd.str && wordDict.find(tmp) != wordDict.end()
                   && hasvisited.find(tmp) == wordDict.end()){
                    q.push(node(tmp, nd.level + 1));
                    hasvisited.insert(tmp);
                }
            }
        }
    }
    int ladderLength(string beginWord, string endWord, unordered_set<string>& wordDict) {
        if(beginWord == endWord) return 1;
        unordered_set<string> hasvisited;
        queue<node> q;
        q.push(node(beginWord, 1));
        while(!q.empty()){
            node nd = q.front();
            q.pop();
            if(isDiffByOne(nd.str, endWord)){
                return nd.level + 1;
            }
            foreach(nd, q, wordDict, hasvisited);
        }
        return 0;
    }
};






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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值