Skip to content

Commit 9533b2b

Browse files
committed
添加了很多章
1 parent 282bb8e commit 9533b2b

13 files changed

+1191
-10
lines changed

C++/LeetCodet题解(C++版).pdf

135 KB
Binary file not shown.

C++/chapBFS.tex

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
\chapter{广度优先搜索}
2+
当题目看不出任何规律,既不能用分治,贪心,也不能用动规时,这时候万能方法——搜索,
3+
就派上用场了。搜索分为广搜和深搜,广搜里面又有普通广搜,双向广搜,A*搜索等。
4+
深搜里面又有普通深搜,回溯法等。
5+
6+
广搜和深搜非常类似(除了在扩展节点这部分不一样),二者有相同的框架,如何表示状态?
7+
如何扩展状态?如何判重?尤其是判重,解决了这个问题,基本上整个问题就解决了。
8+
9+
10+
\section{Word Ladder} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11+
\label{sec:wordladder}
12+
13+
14+
\subsubsection{描述}
15+
Given two words (start and end), and a dictionary, find the length of shortest transformation sequence from start to end, such that:
16+
\begindot
17+
\item Only one letter can be changed at a time
18+
\item Each intermediate word must exist in the dictionary
19+
\myenddot
20+
21+
For example, Given:
22+
23+
\begin{Code}
24+
start = "hit"
25+
end = "cog"
26+
dict = ["hot","dot","dog","lot","log"]
27+
\end{Code}
28+
As one shortest transformation is \code{"hit" -> "hot" -> "dot" -> "dog" -> "cog"}, return its length $5$.
29+
30+
Note:
31+
\begindot
32+
\item Return 0 if there is no such transformation sequence.
33+
\item All words have the same length.
34+
\item All words contain only lowercase alphabetic characters.
35+
\myenddot
36+
37+
38+
\subsubsection{分析}
39+
40+
41+
\subsubsection{代码}
42+
\begin{Code}
43+
//LeetCode, Word Ladder
44+
class Solution {
45+
public:
46+
int ladderLength(string start, string end, unordered_set<string> &dict) {
47+
if (start.size() != end.size()) return 0;
48+
if (start.empty() || end.empty()) return 1; return 0;
49+
int level = 1; // 层次
50+
queue<string> queToPush, queToPop;
51+
52+
queToPop.push(start);
53+
while (dict.size() > 0 && !queToPop.empty()) {
54+
while (!queToPop.empty()) {
55+
string str(queToPop.front());
56+
queToPop.pop();
57+
for (int i = 0; i < str.size(); i++) {
58+
for (char j = 'a'; j <= 'z'; j++) {
59+
if (j == str[i]) continue;
60+
61+
const char temp = str[i];
62+
str[i] = j;
63+
if (str == end) return level + 1; //找到了
64+
65+
if (dict.count(str) > 0) {
66+
queToPush.push(str);
67+
dict.erase(str); // 删除该单词,防止死循环
68+
}
69+
str[i] = temp; // 恢复该单词
70+
}
71+
}
72+
}
73+
swap(queToPush, queToPop); //!!! 交换两个队列
74+
level++;
75+
}
76+
return 0; // 所有单词已经用光,还是找不到通向目标单词的路径
77+
}
78+
};
79+
\end{Code}
80+
81+
82+
\subsubsection{相关题目}
83+
84+
\begindot
85+
\item Word Ladder II,见 \S \ref{sec:wordladderii}
86+
\myenddot
87+
88+
89+
\section{Word Ladder II} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
90+
\label{sec:wordladderii}
91+
92+
93+
\subsubsection{描述}
94+
Given two words (start and end), and a dictionary, find all shortest transformation sequence(s) from start to end, such that:
95+
\begindot
96+
\item Only one letter can be changed at a time
97+
\item Each intermediate word must exist in the dictionary
98+
\myenddot
99+
100+
For example, Given:
101+
\begin{Code}
102+
start = "hit"
103+
end = "cog"
104+
dict = ["hot","dot","dog","lot","log"]
105+
\end{Code}
106+
Return
107+
\begin{Code}
108+
[
109+
["hit","hot","dot","dog","cog"],
110+
["hit","hot","lot","log","cog"]
111+
]
112+
\end{Code}
113+
114+
Note:
115+
\begindot
116+
\item All words have the same length.
117+
\item All words contain only lowercase alphabetic characters.
118+
\myenddot
119+
120+
121+
\subsubsection{分析}
122+
跟 Word Ladder比,这题是求路径本身,不是路径长度,也是BFS,略微麻烦点
123+
124+
125+
\subsubsection{代码}
126+
127+
\begin{Code}
128+
//LeetCode, Word Ladder II
129+
//跟 Word Ladder比,这题是求路径本身,不是路径长度,也是BFS,略微麻烦点
130+
class Solution {
131+
public:
132+
std::vector<std::vector<std::string> > findLadders(std::string start,
133+
std::string end, std::unordered_set<std::string> &dict) {
134+
result_.clear();
135+
std::unordered_map<std::string, std::vector<std::string>> prevMap;
136+
137+
for (auto iter = dict.begin(); iter != dict.end(); ++iter) {
138+
prevMap[*iter] = std::vector<std::string>();
139+
}
140+
141+
std::vector<std::unordered_set<std::string>> candidates(2);
142+
143+
int current = 0;
144+
int previous = 1;
145+
146+
candidates[current].insert(start);
147+
148+
while (true) {
149+
current = !current;
150+
previous = !previous;
151+
152+
// 从dict中删除previous中的单词,避免自己指向自己
153+
for (auto iter = candidates[previous].begin();
154+
iter != candidates[previous].end(); ++iter) {
155+
dict.erase(*iter);
156+
}
157+
158+
candidates[current].clear();
159+
160+
for (auto iter = candidates[previous].begin();
161+
iter != candidates[previous].end(); ++iter) {
162+
for (size_t pos = 0; pos < iter->size(); ++pos) {
163+
std::string word = *iter;
164+
for (int i = 'a'; i <= 'z'; ++i) {
165+
if (word[pos] == i) continue;
166+
167+
word[pos] = i;
168+
169+
if (dict.count(word) > 0) {
170+
prevMap[word].push_back(*iter);
171+
candidates[current].insert(word);
172+
}
173+
}
174+
}
175+
}
176+
177+
if (candidates[current].size() == 0) return result_; // 此题无解
178+
if (candidates[current].count(end)) break; // 没看懂
179+
}
180+
181+
std::vector<std::string> path;
182+
GeneratePath(prevMap, path, end);
183+
184+
return result_;
185+
}
186+
187+
private:
188+
std::vector<std::vector<std::string>> result_;
189+
190+
void GeneratePath(
191+
std::unordered_map<std::string, std::vector<std::string>> &prevMap,
192+
std::vector<std::string>& path, const std::string& word) {
193+
if (prevMap[word].size() == 0) {
194+
path.push_back(word);
195+
std::vector<std::string> curPath = path;
196+
reverse(curPath.begin(), curPath.end());
197+
result_.push_back(curPath);
198+
path.pop_back();
199+
return;
200+
}
201+
202+
path.push_back(word);
203+
for (auto iter = prevMap[word].begin(); iter != prevMap[word].end();
204+
++iter) {
205+
GeneratePath(prevMap, path, *iter);
206+
}
207+
path.pop_back();
208+
}
209+
};
210+
\end{Code}
211+
212+
213+
\subsubsection{相关题目}
214+
215+
\begindot
216+
\item Word Ladder,见 \S \ref{sec:wordladder}
217+
\myenddot

C++/chapDFS.tex

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
\chapter{深度优先搜索}
2+
3+
4+
\section{Palindrome Partitioning} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5+
\label{sec:palindrome-partitioning}
6+
7+
8+
\subsubsection{描述}
9+
Given a string s, partition s such that every substring of the partition is a palindrome.
10+
11+
Return all possible palindrome partitioning of s.
12+
13+
For example, given \code{s = "aab"},
14+
Return
15+
\begin{Code}
16+
[
17+
["aa","b"],
18+
["a","a","b"]
19+
]
20+
\end{Code}
21+
22+
23+
\subsubsection{分析}
24+
在每一步都可以判断中间结果是否为合法结果,用回溯法。
25+
26+
一个长度为n的字符串,有n+1个地方可以砍断,每个地方可断可不断,因此复杂度为$O(2^{n+1})$
27+
28+
29+
\subsubsection{代码}
30+
\begin{Code}
31+
//LeetCode, Palindrome Partitioning
32+
class Solution {
33+
public:
34+
vector<vector<string>> partition(string s) {
35+
vector<vector<string>> result;
36+
vector<string> output; // 一个partition方案
37+
DFS(s, 0, output, result);
38+
return result;
39+
}
40+
// 搜索必须以s[start]开头的partition方案
41+
// 如果一个字符串长度为n,则可以插入n+1个隔板,复制度为O(2^{n+1})
42+
void DFS(string &s, int start, vector<string>& output,
43+
vector<vector<string>> &result) {
44+
if (start == s.size()) {
45+
result.push_back(output);
46+
return;
47+
}
48+
for (int i = start; i < s.size(); i++) {
49+
if (isPalindrome(s, start, i)) { // 从i位置砍一刀
50+
output.push_back(s.substr(start, i - start + 1));
51+
DFS(s, i + 1, output, result); // 继续往下砍
52+
output.pop_back(); // 撤销上一个push_back的砍
53+
}
54+
}
55+
}
56+
bool isPalindrome(string &s, int start, int end) {
57+
while (start < end) {
58+
if (s[start] != s[end]) return false;
59+
start++;
60+
end--;
61+
}
62+
return true;
63+
}
64+
};
65+
\end{Code}
66+
67+
68+
\subsubsection{相关题目}
69+
70+
\begindot
71+
\item Palindrome Partitioning II,见 \S \ref{sec:palindrome-partitioning-ii}
72+
\myenddot
73+

C++/chapDivideAndConquer.tex

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
\chapter{分治法}
2+
3+
4+
\section{Pow(x,n)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5+
6+
7+
\subsubsection{描述}
8+
Implement pow(x, n).
9+
10+
11+
\subsubsection{分析}
12+
二分法,$x^n = x^{n/2} \times x^{n/2} \times x^{n\%2}$
13+
14+
15+
\subsubsection{代码}
16+
\begin{Code}
17+
//LeetCode, Pow(x, n)
18+
// 二分法,$x^n = x^{n/2} * x^{n/2} * x^{n\%2}$
19+
class Solution {
20+
private:
21+
double power(double x, int n) {
22+
if (n == 0) return 1;
23+
double v = power(x, n / 2);
24+
if (n % 2 == 0) return v * v;
25+
else return v * v * x;
26+
}
27+
public:
28+
double pow(double x, int n) {
29+
if (n < 0) return 1.0 / power(x, -n);
30+
else return power(x, n);
31+
}
32+
};
33+
\end{Code}
34+
35+
36+
\subsubsection{相关题目}
37+
38+
\begindot
39+
\item
40+
\myenddot

0 commit comments

Comments
 (0)