Skip to content

Commit 648fcc7

Browse files
committed
批量提交
1 parent bc48c5d commit 648fcc7

8 files changed

+669
-6
lines changed

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

69.6 KB
Binary file not shown.

C++/chapBruteforce.tex

Lines changed: 226 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,226 @@
1+
\chapter{暴力枚举法}
2+
3+
4+
\section{Subsets} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5+
\label{sec:subsets}
6+
7+
8+
\subsubsection{描述}
9+
Given a set of distinct integers, $S$, return all possible subsets.
10+
11+
Note:
12+
\begindot
13+
\item Elements in a subset must be in non-descending order.
14+
\item The solution set must not contain duplicate subsets.
15+
\myenddot
16+
17+
For example, If \code{S = [1,2,3]}, a solution is:
18+
\begin{Code}
19+
[
20+
[3],
21+
[1],
22+
[2],
23+
[1,2,3],
24+
[1,3],
25+
[2,3],
26+
[1,2],
27+
[]
28+
]
29+
\end{Code}
30+
31+
32+
\subsection{增量构造法}
33+
每个元素,都有两种选择,选或者不选。
34+
35+
\subsubsection{代码}
36+
\begin{Code}
37+
// LeetCode, Subsets
38+
// 增量构造法,朴素深搜
39+
class Solution {
40+
public:
41+
vector<vector<int> > subsets(vector<int> &S) {
42+
vector<vector<int> > result;
43+
vector<int> cur;
44+
std::sort(S.begin(), S.end()); // 本题对顺序有要求,需要排序
45+
46+
subsets(S, cur, 0, result);
47+
return result;
48+
}
49+
50+
private:
51+
static void subsets(const vector<int> &S, vector<int> &cur, int step,
52+
vector<vector<int> > &result) {
53+
if (step == S.size()) {
54+
result.push_back(cur);
55+
return;
56+
}
57+
// 不选S[step]
58+
subsets(S, cur, step + 1, result);
59+
// 选S[step]
60+
cur.push_back(S[step]);
61+
subsets(S, cur, step + 1, result);
62+
cur.pop_back();
63+
}
64+
};
65+
\end{Code}
66+
67+
68+
\subsection{位向量法}
69+
开一个位向量\fn{bool selected[n]},每个元素可以选或者不选。
70+
71+
72+
\subsubsection{代码}
73+
\begin{Code}
74+
// LeetCode, Subsets
75+
// 位向量法,也属于朴素深搜
76+
class Solution {
77+
public:
78+
vector<vector<int> > subsets(vector<int> &S) {
79+
vector<vector<int> > result;
80+
bool *selected = new bool[S.size()];
81+
std::sort(S.begin(), S.end()); // 本题对顺序有要求,需要排序
82+
83+
subsets(S, selected, 0, result);
84+
delete[] selected;
85+
return result;
86+
}
87+
88+
private:
89+
static void subsets(const vector<int> &S, bool selected[], int step,
90+
vector<vector<int> > &result) {
91+
if (step == S.size()) {
92+
vector<int> subset;
93+
for (int i = 0; i < S.size(); i++) {
94+
if (selected[i]) subset.push_back(S[i]);
95+
}
96+
result.push_back(subset);
97+
return;
98+
}
99+
// 不选S[step]
100+
selected[step] = false;
101+
subsets(S, selected, step + 1, result);
102+
// 选S[step]
103+
selected[step] = true;
104+
subsets(S, selected, step + 1, result);
105+
}
106+
};
107+
\end{Code}
108+
109+
110+
\subsection{二进制法}
111+
本方法的前提是:集合的元素不超过int位数。用一个int整数表示位向量,第$i$位为1,则表示选择$S[i]$,为0则不选择。例如\fn{S=\{A,B,C,D\}},则\fn{0110=6}表示子集\fn{\{B,C\}}。
112+
113+
这种方法最巧妙。因为它不仅能生成子集,还能方便的表示集合的并、交、差等集合运算。设两个集合的位向量分别为$B_1$$B_2$,则$B_1|B_2, B_1 \& B_2, B_1 \^ B_2$分别对应集合的并、交、对称差。
114+
115+
\begin{Code}
116+
// LeetCode, Subsets
117+
// 二进制法
118+
class Solution {
119+
public:
120+
vector<vector<int> > subsets(vector<int> &S) {
121+
vector<vector<int> > result;
122+
std::sort(S.begin(), S.end()); // 本题对顺序有要求,需要排序
123+
const size_t n = S.size();
124+
vector<int> v;
125+
126+
for (size_t i = 0; i < 1 << n; i++) {
127+
for (size_t j = 0; j < n; j++) {
128+
if (i & 1 << j) v.push_back(S[j]);
129+
}
130+
result.push_back(v);
131+
v.clear();
132+
}
133+
return result;
134+
}
135+
};
136+
\end{Code}
137+
138+
139+
\subsubsection{代码}
140+
\begin{Code}
141+
142+
\end{Code}
143+
144+
\subsubsection{相关题目}
145+
\begindot
146+
\item Subsets II,见 \S \ref{sec:subsets-ii}
147+
\myenddot
148+
149+
150+
\section{Subsets II} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
151+
\label{sec:subsets-ii}
152+
153+
154+
\subsubsection{描述}
155+
Given a collection of integers that might contain duplicates, $S$, return all possible subsets.
156+
157+
Note:
158+
159+
Elements in a subset must be in non-descending order.
160+
The solution set must not contain duplicate subsets.
161+
For example,
162+
If \fn{S = [1,2,2]}, a solution is:
163+
\begin{Code}
164+
[
165+
[2],
166+
[1],
167+
[1,2,2],
168+
[2,2],
169+
[1,2],
170+
[]
171+
]
172+
\end{Code}
173+
174+
175+
\subsubsection{分析}
176+
这题有重复元素,但本质上,跟上一题很类似,上一题中元素没有重复,相当于每个元素只能选0或1次,这里扩充到了每个元素可以选0到若干次而已。
177+
178+
179+
\subsubsection{代码}
180+
\begin{Code}
181+
// LeetCode, Subsets II
182+
class Solution {
183+
public:
184+
vector<vector<int> > subsetsWithDup(vector<int> &S) {
185+
vector<vector<int> > result;
186+
std::sort(S.begin(), S.end()); // 本题对顺序有要求,需要排序
187+
std::vector<int> count(S.back() - S.front() + 1, 0);
188+
// 计算所有元素的个数
189+
for(auto i = S.begin(); i != S.end(); i++) {
190+
count[*i - S[0]]++;
191+
}
192+
193+
// 每个元素选择了多少个
194+
std::vector<int> selected(S.back() - S.front() + 1, -1);
195+
196+
subsets(S, count, selected, 0, result);
197+
return result;
198+
}
199+
200+
private:
201+
static void subsets(const vector<int> &S, vector<int> &count,
202+
vector<int> &selected, size_t step, vector<vector<int> > &result) {
203+
if (step == count.size()) {
204+
vector<int> subset;
205+
for(size_t i = 0; i < selected.size(); i++) {
206+
for (int j = 0; j < selected[i]; j++) {
207+
subset.push_back(i+S[0]);
208+
}
209+
}
210+
result.push_back(subset);
211+
return;
212+
}
213+
214+
for (int i = 0; i <= count[step]; i++) {
215+
selected[step] = i;
216+
subsets(S, count, selected, step + 1, result);
217+
}
218+
}
219+
};
220+
\end{Code}
221+
222+
223+
\subsubsection{相关题目}
224+
\begindot
225+
\item Subsets,见 \S \ref{sec:subsets}
226+
\myenddot

C++/chapDivideAndConquer.tex

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ \chapter{分治法}
22

33

44
\section{Pow(x,n)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5+
\label{sec:pow}
56

67

78
\subsubsection{描述}
@@ -36,5 +37,54 @@ \subsubsection{代码}
3637
\subsubsection{相关题目}
3738

3839
\begindot
39-
\item
40+
\item Sqrt(x),见 \S \ref{sec:sqrt}
41+
\myenddot
42+
43+
44+
\section{Sqrt(x)} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
45+
\label{sec:sqrt}
46+
47+
\subsubsection{描述}
48+
Implement int \fn{sqrt(int x)}.
49+
50+
Compute and return the square root of \fn{x}.
51+
52+
53+
\subsubsection{分析}
54+
二分查找
55+
56+
57+
\subsubsection{代码}
58+
\begin{Code}
59+
// LeetCode, Longest Substring Without Repeating Characters
60+
// 二分查找
61+
class Solution {
62+
public:
63+
int sqrt(int x) {
64+
int left = 1, right = x / 2;
65+
int mid;
66+
int last_mid; // 记录最近一次mid
67+
68+
if (x < 2) return x;
69+
70+
while(left <= right) {
71+
mid = left + (right - left) / 2;
72+
if(x / mid > mid) { // 不要用 x > mid * mid,会溢出
73+
left = mid + 1;
74+
last_mid = mid;
75+
} else if(x / mid < mid) {
76+
right = mid - 1;
77+
} else {
78+
return mid;
79+
}
80+
}
81+
return last_mid;
82+
}
83+
};
84+
\end{Code}
85+
86+
87+
\subsubsection{相关题目}
88+
\begindot
89+
\item Pow(x),见 \S \ref{sec:pow}
4090
\myenddot

C++/chapGreedy.tex

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,55 @@ \subsubsection{相关题目}
7777
\begindot
7878
\item Best Time to Buy and Sell Stock,见 \S \ref{sec:best-time-to-buy-and-sell-stock}
7979
\item Best Time to Buy and Sell Stock III,见 \S \ref{sec:best-time-to-buy-and-sell-stock-iii}
80-
\myenddot
80+
\myenddot
81+
82+
83+
\section{Longest Substring Without Repeating Characters} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
84+
\label{sec:longest-substring-without-repeating-characters}
85+
86+
87+
\subsubsection{描述}
88+
Given a string, find the length of the longest substring without repeating characters. For example, the longest substring without repeating letters for \code{"abcabcbb"} is \code{"abc"}, which the length is 3. For \code{"bbbbb"} the longest substring is \code{"b"}, with the length of 1.
89+
90+
91+
\subsubsection{分析}
92+
假设子串里含有重复字符,则父串一定含有重复字符,单个子问题就可以决定父问题,因此可以用贪心法。跟动规不同,动规里,单个子问题只能影响父问题,不足以决定父问题。
93+
94+
从左往右扫描,当遇到重复字母时,以上一个重复字母的\fn{index+1},作为新的搜索起始位置,直到最后一个字母,复杂度是$O(n)$。如图~\ref{fig:longest-substring-without-repeating-characters}所示。
95+
96+
\begin{center}
97+
\includegraphics[width=300pt]{longest-substring-without-repeating-characters.png}\\
98+
\figcaption{不含重复字符的最长子串}\label{fig:longest-substring-without-repeating-characters}
99+
\end{center}
100+
101+
102+
\subsubsection{代码}
103+
\begin{Code}
104+
// LeetCode, Longest Substring Without Repeating Characters
105+
// 贪心法
106+
class Solution {
107+
public:
108+
int lengthOfLongestSubstring(string s) {
109+
const int ASCII_MAX = 26;
110+
int last[ASCII_MAX]; // 记录字符上次出现过的位置
111+
std::fill(last, last + ASCII_MAX, -1); // 0也是有效位置,因此初始化为-1
112+
int len = 0, max_len = 0;
113+
for (size_t i = 0; i < s.size(); i++, len++) {
114+
if (last[s[i] - 'a'] >= 0) {
115+
max_len = max(len, max_len);
116+
len = 0;
117+
i = last[s[i] - 'a'] + 1;
118+
std::fill(last, last + ASCII_MAX, -1); // 重新开始
119+
}
120+
last[s[i] - 'a'] = i;
121+
}
122+
return max(len, max_len); // 别忘了最后一次,例如"abcd"
123+
}
124+
};
125+
\end{Code}
126+
127+
128+
\subsubsection{相关题目}
129+
\begindot
130+
\item
131+
\myenddot

0 commit comments

Comments
 (0)