单词接龙问题:双向BFS解法

单词接龙问题

题目:
给定两个单词(beginWord 和 endWord)和一个字典,找到从 beginWord 到 endWord的最短转换序列的长度。转换需遵循如下规则:

  • 每次转换只能改变一个字母。 转换过程中的中间单词必须是字典中的单词。

说明:

  • 如果不存在这样的转换序列,返回 0。
  • 所有单词具有相同的长度。
  • 所有单词只由小写字母组成。
  • 字典中不存在重复的单词。
  • 你可以假设beginWord 和 endWord 是非空的,且二者不相同。

双向BFS

  • 使用两个set,分别从start和end两头开始BFS。
  • 每次选择较小的set开始BFS, 也就是将小的作为start,大的作为end。
  • 如果end中能找到start,就结束。
  • 否则,在访问set中加入访问记录,并加入到tmp中,作为子节点。
/*
 * @lc app=leetcode.cn id=127 lang=cpp
 *
 * [127] 单词接龙
 */

// @lc code=start
//双向BFS
class Solution {
public:
    int ladderLength(string beginWord, string endWord, vector<string> &wordList) {
        unordered_set<string> dict(wordList.begin(), wordList.end());
        //字典中没有endWord,直接退出
        if (dict.find(endWord) == dict.end()) {
            return 0;
        }
        unordered_set<string> beginSet, endSet, tmp, visited;
        beginSet.insert(beginWord);
        endSet.insert(endWord);
        int len = 1;
        while (!beginSet.empty() && !endSet.empty()) {
            //交换beginSet和endSet,每次都从最小集合分叉,以最快地从两边往中间搜索
            if (beginSet.size() > endSet.size()) {
                tmp = beginSet;
                beginSet = endSet;
                endSet = tmp;
            }
            tmp.clear();
            for (string word : beginSet) {
                for (int i = 0; i < word.size(); i++) {
                    char old = word[i];
                    for (char c = 'a'; c <= 'z'; c++) {
                        if (old == c) {
                            continue;
                        }
                        word[i] = c;
                        // terminator
                        if (endSet.find(word) != endSet.end()) {
                            return len + 1;
                        }
                        //未访问过,且字典中存在word,则加入访问记录且加入tmp作为下一步要分叉的节点
                        if (visited.find(word) == visited.end() && dict.find(word) != dict.end()) {
                            tmp.insert(word);
                            visited.insert(word);
                        }
                    }
                    word[i] = old;
                }
            }
            //更新beginSet
            beginSet = tmp;
            len++;
        }
        return 0;
    }
};
// @lc code=end

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值