[leetcode] 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 intermediate word must exist in the word list

For example,

Given:
beginWord = "hit"
endWord = "cog"
wordList = ["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.

这道题是求单词衍变的最小步骤数,题目难度为Medium。

比较典型的广度优先搜索的题目,从初始单词开始进行一步衍变,如果新单词等于最终单词即可返回;如果新单词不等于最终单词且新单词在字典中,则将新单词存入队列(这里将新单词从字典中删除来避免回环并提高后续查找效率),之后再对队列中单词进行新的衍变直至找到最终单词或队列为空。具体代码:

class Solution {
public:
    int ladderLength(string beginWord, string endWord, unordered_set<string>& wordList) {
        queue<string> next;
        int length = 1;
        
        next.push(beginWord);
        while(!next.empty()) {
            int sz = next.size();
            for(int i=0; i<sz; ++i) {
                string cur = next.front();
                next.pop();
                if(cur == endWord) return length;
                else {
                    for(int j=0; j<cur.size(); ++j) {
                        char c = cur[j];
                        for(char ch = 'a'; ch <= 'z'; ++ch) {
                            cur[j] = ch;
                            if(wordList.find(cur) != wordList.end()) {
                                next.push(cur);
                                wordList.erase(cur);
                            }
                        }
                        cur[j] = c;
                    }
                }
            }
            ++length;
        }
        
        return 0;
    }
};
代码执行时间280ms左右,看了下别人的代码还有效率更高的方法,分享给大家。从两端两个方向上进行广度优先搜索,每次选择两端中单词数少的一方进行遍历,这样执行效率有了明显提升。具体代码:
class Solution {
public:
    int ladderLength(string beginWord, string endWord, unordered_set<string>& wordList) {
        unordered_set<string> head, tail;
        int length = 2;
        
        head.insert(beginWord);
        tail.insert(endWord);
        while(!head.empty() && !tail.empty()) {
            if(head.size() > tail.size()) swap(head, tail);
            unordered_set<string> next;
            for(auto it = head.begin(); it != head.end(); ++it) {
                string cur = *it;
                for(int i=0; i<cur.size(); ++i) {
                    char c = cur[i];
                    for(char ch = 'a'; ch <= 'z'; ++ch) {
                        cur[i] = ch;
                        if(tail.find(cur) != tail.end()) return length;
                        if(wordList.find(cur) != wordList.end()) {
                            next.insert(cur);
                            wordList.erase(cur);
                        }
                    }
                    cur[i] = c;
                }
            }
            ++length;
            swap(head, next);
        }
        
        return 0;
    }
};
以上代码执行时间达到了79ms,不过始终没想明白为何选择单词少的一方进行遍历能够提高执行效率,明白的同学可以留言解下惑。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值