首页 > 代码库 > 《Cracking the Coding Interview》——第18章:难题——题目10

《Cracking the Coding Interview》——第18章:难题——题目10

2014-04-29 04:22

题目:给定一堆长度都相等的单词,和起点、终点两个单词,请从这堆单词中寻找一条变换路径,把起点词变成终点词,要求每次变换只能改一个字母。

解法:Leetcode中有Word Ladder,这题基本思路一致。

代码:

 1 // 18.10 Given a list of words, all of same length. Given a source and a destionation words, you have to check if there exists a path between the two. Every time you may change only one letter in the word.
 2 // This is my code from leetcode problem set: word ladder
 3 #include <string>
 4 #include <unordered_map>
 5 #include <unordered_set>
 6 #include <vector>
 7 using namespace std;
 8 
 9 class Solution {
10 public:
11     vector<vector<string> > findLadders(string start, string end, unordered_set<string> &dict) {
12         unordered_map<string, vector<string> > back_trace;
13         vector<unordered_set<string> > level(2);
14         
15         dict.insert(start);
16         dict.insert(end);
17         
18         int flag, nflag;
19         flag = 0;
20         nflag = !flag;
21         level[flag].insert(start);
22         
23         unordered_set<string>::iterator usit;
24         char ch, old_ch;
25         string word;
26         while (true) {
27             flag = !flag;
28             nflag = !nflag;
29             level[flag].clear();
30             for (usit = level[nflag].begin(); usit != level[nflag].end(); ++usit) {
31                 dict.erase(*usit);
32             }
33             for (usit = level[nflag].begin(); usit != level[nflag].end(); ++usit) {
34                 word = *usit;
35                 for (size_t i = 0; i < word.size(); ++i) {
36                     old_ch = word[i];
37                     for (ch = a; ch <= z; ++ch) {
38                         if (ch == old_ch) {
39                             continue;
40                         }
41                         word[i] = ch;
42                         if (dict.find(word) != dict.end()) {
43                             back_trace[word].push_back(*usit);
44                             level[flag].insert(word);
45                         }
46                     }
47                     word[i] = old_ch;
48                 }
49             }
50             if (level[flag].empty() || level[flag].count(end) > 0) {
51                 // found or not found
52                 break;
53             }
54         }
55         
56         single_result.clear();
57         for (size_t i = 0; i < result.size(); ++i) {
58             result[i].clear();
59         }
60         result.clear();
61         
62         if (!back_trace.empty()) {
63             recorverPath(back_trace, end);
64         }
65         
66         return result;
67     }
68 private:
69     vector<vector<string> > result;
70     vector<string> single_result;
71     
72     void recorverPath(unordered_map<string, vector<string> > &back_trace, string cur) {
73         if (back_trace.count(cur) == 0) {
74             // this word has no back trace, it is unreachable.
75             vector<string> single_path(single_result);
76             
77             single_path.push_back(cur);
78             reverse(single_path.begin(), single_path.end());
79             result.push_back(single_path);
80             return;
81         }
82         
83         const vector<string> &v = back_trace[cur];
84         vector<string>::const_iterator usit;
85         
86         single_result.push_back(cur);
87         for (usit = v.begin(); usit != v.end(); ++usit) {
88             recorverPath(back_trace, *usit);
89         }
90         single_result.pop_back();
91     }
92 };