[LeetCode] Word Ladder

本文介绍了一种使用广度优先搜索(BFS)算法解决单词阶梯问题的方法,通过将单词转换过程构建成图,从起点单词开始遍历直至到达终点单词,实现了寻找最短转换路径的目标。

Well, this problem has a nice BFS structure.

Let's see the example in the problem statement.

start = "hit"

end = "cog"

dict = ["hot", "dot", "dog", "lot", "log"]

Since only one letter can be changed at a time, if we start from "hit", we can only change to those words which have only one different letter from it, like "hot". Putting in graph-theoretic terms, we can say that "hot" is a neighbor of "hit".

The idea is simpy to begin from start, then visit its neighbors, then the non-visited neighbors of its neighbors... Well, this is just the typical BFS structure.

To simplify the problem, we insert end into dict. Once we meet end during the BFS, we know we have found the answer. We maintain a variable ladder for the current distance of the transformation and update it by ladder++ once we finish a round of BFS search (note that it should fit the definition of the distance in the problem statement). Also, to avoid visiting a word for more than once, we erase it from dict once it is visited.

The code is as follows.

 1 class Solution {
 2 public:
 3     int ladderLength(string beginWord, string endWord, unordered_set<string>& wordDict) {
 4         wordDict.erase(beginWord);
 5         wordDict.insert(endWord);
 6         int ladder = 2, len = beginWord.length();
 7         queue<string> nextWords;
 8         nextWords.push(beginWord);
 9         while (!nextWords.empty()) {
10             int num = nextWords.size();
11             for (int i = 0; i < num; i++) {
12                 string word = nextWords.front();
13                 nextWords.pop();
14                 for (int p = 0; p < len; p++) {
15                     char letter = word[p];
16                     for (int j = 0; j < 26; j++) {
17                         word[p] = 'a' + j;
18                         if (wordDict.find(word) != wordDict.end()) {
19                             if (word == endWord) return ladder;
20                             wordDict.erase(word);
21                             nextWords.push(word);
22                         }
23                     }
24                     word[p] = letter;
25                 }
26             }
27             ladder++;
28         }
29         return 0;
30     }
31 };

The above code can still be speed up if we also begin from end. Once we meet the same word from start and end, we know we are done. This link provides a nice two-end search solution. I rewrite the code below for better readability. At each round of BFS, depending on the relative size of nextWords and prevWords, we swap the smaller one to the working setto reduce the running time (lines 12 - 13). 

 1 class Solution {
 2 public:
 3     int ladderLength(string beginWord, string endWord, unordered_set<string>& wordDict) {
 4         wordDict.erase(beginWord);
 5         wordDict.erase(endWord);
 6         unordered_set<string> nextWords;
 7         unordered_set<string> prevWords;
 8         nextWords.insert(beginWord);
 9         prevWords.insert(endWord);
10         int ladder = 2, len = beginWord.length();
11         while (!nextWords.empty() && !prevWords.empty()) {
12             if (nextWords.size() > prevWords.size())
13                 swap(nextWords, prevWords);
14             unordered_set<string>::iterator itr = nextWords.begin();
15             unordered_set<string> temp;
16             for (; itr != nextWords.end(); itr++) {
17                 string word = *itr;
18                 for (int p = 0; p < len; p++) {
19                     char letter = word[p];
20                     for (int j = 0; j < 26; j++) {
21                         word[p] = 'a' + j;
22                         if (prevWords.find(word) != prevWords.end())
23                             return ladder;
24                         if (wordDict.find(word) != wordDict.end()) {
25                             temp.insert(word);
26                             wordDict.erase(word);
27                         }
28                     }
29                     word[p] = letter;
30                 }
31             }
32             swap(nextWords, temp);
33             ladder++;
34         }
35         return 0;
36     }
37 };

 

转载于:https://www.cnblogs.com/jcliBlogger/p/4599041.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值