《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 };

《Cracking the Coding Interview》——第18章:难题——题目10,码迷,mamicode.com

时间: 2024-12-25 20:55:05

《Cracking the Coding Interview》——第18章:难题——题目10的相关文章

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

2014-04-29 04:18 题目:有一连串的数被读入,设计一个数据结构,能随时返回当前所有数的中位数. 解法:用一个大顶堆,一个小顶堆将数分成数量最接近的两份,就能轻松得到中位数了. 代码: 1 // 18.9 A stream of integers are passed to you, you have to tell me the median as they keep coming in. 2 #include <climits> 3 #include <iostream&

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

2014-04-29 04:40 题目:给定一个字母组成的矩阵,和一个包含一堆单词的词典.请从矩阵中找出一个最大的子矩阵,使得从左到右每一行,从上到下每一列组成的单词都包含在词典中. 解法:O(n^3)级别的时间和空间进行动态规划.这道题目和第17章的最后一题很像,由于这题的时间复杂度实在是高,我动手写了字典树进行加速.如果单纯用哈希表来作为词典,查询效率实际会达到O(n)级别,导致最终的算法复杂度为O(n^4).用字典树则可以加速到O(n^3),因为对于一个字符串"abcd",只需要

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

2014-04-29 04:30 题目:给定一个由'0'或者'1'构成的二维数组,找出一个四条边全部由'1'构成的正方形(矩形中间可以有'0'),使得矩形面积最大. 解法:用动态规划思想,记录二维数组每个元素向上下左右四个方向各有多少个连续的'1',然后用O(n^3)时间计算出满足条件的最大正方形.时间复杂度O(n^3),空间复杂度O(n^2). 代码: 1 // 18.11 Given an NxN matrix of 0s and 1s, find out a subsquare whose

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

2014-04-29 04:36 题目:最大子数组和的二位扩展:最大子矩阵和. 解法:一个维度上进行枚举,复杂度O(n^2):另一个维度执行最大子数组和算法,复杂度O(n).总体时间复杂度为O(n^3),还需要O(n)额外空间. 代码: 1 // 18.12 Given an n x n matrix, find the submatrix with largest sum. Return the sum as the result. 2 #include <algorithm> 3 #inc

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

2014-04-29 02:27 题目:找出10亿个数中最小的100万个数,假设内存可以装得下. 解法1:内存可以装得下?可以用快速选择算法得到无序的结果.时间复杂度总体是O(n)级别,但是常系数不小. 代码: 1 // 18.6 Find the smallest one million number among one billion numbers. 2 // Suppose one billion numbers can fit in memory. 3 // I'll use quic

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

2014-04-29 03:05 题目:给定一个词典,其中某些词可能能够通过词典里其他的词拼接而成.找出这样的组合词里最长的一个. 解法:Leetcode上有Word Break这道题,和这题基本思路一致. 代码: 1 // 18.7 Given a list of words, find out the longest word made of other words in the list. 2 #include <iostream> 3 #include <string> 4

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

2014-04-29 00:59 题目:设计一个洗牌算法,效率尽量快点,必须等概率. 解法:每次随机抽一张牌出来,最后都抽完了,也就洗好了.时间复杂度O(n^2),请看代码. 代码: 1 // 18.2 shuffle a deck of 52 cards, it must be perfect random. 2 #include <cstdio> 3 #include <cstdlib> 4 #include <ctime> 5 #include <vecto

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

2014-04-29 01:02 题目:从m个整数里随机选出n个整数,要求等概率. 解法:和洗牌的算法类似,每次随机抽出一个数,抽n次即可.时间复杂度O(m * n),空间复杂度O(m). 代码: 1 // 18.3 pick m integers randomly from an array of n integer. 2 #include <cstdio> 3 #include <cstdlib> 4 #include <ctime> 5 #include <

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

2014-04-29 01:51 题目:你有一个文本文件,每行一个单词.给定两个单词,请找出这两个单词在文件中出现的其中一对位置,使得这两个位置的距离最短. 解法:我的思路是建立倒排索引,计算出所有单词出现的所有位置.下面代码只给出了两个索引的处理方法.倒排索引一般以链表的形式出现,通过顺序扫描两个链表,类似归并排序算法中的merge过程,就能够找出最短距离.请看代码. 代码: 1 // 18.5 Given a text file containing words, find the shor