Skip to content

Commit 4f076f8

Browse files
committed
完成了tree, list, array的习题
1 parent 9533b2b commit 4f076f8

File tree

8 files changed

+2083
-37
lines changed

8 files changed

+2083
-37
lines changed

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

147 KB
Binary file not shown.

C++/abstract.tex

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,9 @@ \subsubsection{内容简介}
1010
\item 所有代码都是单一文件。这是因为一般OJ网站,提交代码的时候只有一个文本框,如果还是
1111
按照标准做法,比如分为头文件.h和源代码.cpp,无法在网站上提交;
1212

13-
\item 大量使用 STL,让代码更短,shorter is better
13+
\item Shorter is better。能递归则一定不用栈;能用STL则一定不自己实现。
1414

15-
\item 不提倡防御式编程。不需要检查malloc()/new 返回的指针是否为NULL;不需要检查内部函数入口
16-
参数的有效性;使用纯C基于对象编程时,调用对象的成员方法,不需要检查对象自身是否为NULL。
15+
\item 不提倡防御式编程。不需要检查malloc()/new 返回的指针是否为NULL;不需要检查内部函数入口参数的有效性;使用纯C基于对象编程时,调用对象的成员方法,不需要检查对象自身是否为NULL。
1716
\myenddot
1817

1918
本手册假定读者已经学过《数据结构》\footnote{《数据结构》,严蔚敏等著,清华大学出版社,

C++/chapDynamicProgramming.tex

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,111 @@
11
\chapter{动态规划}
22

33

4+
\section{Maximum Subarray} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5+
\label{sec:maximum-subarray}
6+
7+
8+
\subsubsection{描述}
9+
Find the contiguous subarray within an array (containing at least one number) which has the largest sum.
10+
11+
For example, given the array \code{[−2,1,−3,4,−1,2,1,−5,4]},
12+
the contiguous subarray \code{[4,−1,2,1]} has the largest \code{sum = 6}.
13+
14+
15+
\subsubsection{分析}
16+
最大连续子序列和,非常经典的题。
17+
18+
当我们从头到尾遍历这个数组的时候,对于数组里的一个整数,它有几种选择呢?它只有两种选择: 1、加入之前的SubArray;2. 自己另起一个SubArray。那什么时候会出现这两种情况呢?
19+
20+
如果之前SubArray的总体和大于0的话,我们认为其对后续结果是有贡献的。这种情况下我们选择加入之前的SubArray
21+
22+
如果之前SubArray的总体和为0或者小于0的话,我们认为其对后续结果是没有贡献,甚至是有害的(小于0时)。这种情况下我们选择以这个数字开始,另起一个SubArray。
23+
24+
设状态为d[j],表示以S[j]结尾的最大连续子序列和,则状态转移方程如下:
25+
\begin{eqnarray}
26+
d[j] &=& \max\left\{d[j-1]+S[j],S[j]\right\}, \text{ 其中 }1 \leq j \leq n \nonumber \\
27+
target &=& \max\left\{d[j]\right\}, \text{ 其中 }1 \leq j \leq n \nonumber
28+
\end{eqnarray}
29+
30+
解释如下:
31+
\begindot
32+
\item 情况一,S[j]不独立,与前面的某些数组成一个连续子序列,则最大连续子序列和为$d[j-1]+S[j]$
33+
\item 情况二,S[j]独立划分成为一段,即连续子序列仅包含一个数S[j],则最大连续子序列和为$S[j]$
34+
\myenddot
35+
36+
其他思路:
37+
\begindot
38+
\item 思路1:直接在i到j之间暴力枚举,复杂度是$O(n^3)$
39+
\item 思路2:处理后枚举,连续子序列的和等于两个前缀和之差,复杂度$O(n^2)$
40+
\item 思路3:分治法,把序列分为两段,分别求最大连续子序列和,然后归并,复杂度$O(n\log n)$
41+
\item 思路4:把思路2$O(n^2)$的代码稍作处理,得到$O(n)$的算法
42+
\item 思路5:当成M=1的最大M子段和
43+
\myenddot
44+
45+
46+
\subsubsection{代码}
47+
\begin{Code}
48+
// LeetCode, Maximum Subarray
49+
class Solution {
50+
public:
51+
int maxSubArray(int A[], int n) {
52+
return mcss(A, n);
53+
//return mcss_dp(A, n);
54+
}
55+
private:
56+
/**
57+
* @brief 最大连续子序列和,思路四
58+
* @param[in] S 数列
59+
* @param[in] n 数组的长度
60+
* @return 最大连续子序列和
61+
*/
62+
static int mcss(int S[], int n) {
63+
int i, result, cur_min;
64+
int *sum = (int*) malloc((n + 1) * sizeof(int)); // 前n项和
65+
66+
sum[0] = 0;
67+
result = INT_MIN;
68+
cur_min = sum[0];
69+
for (i = 1; i <= n; i++) {
70+
sum[i] = sum[i - 1] + S[i - 1];
71+
}
72+
for (i = 1; i <= n; i++) {
73+
result = max(result, sum[i] - cur_min);
74+
cur_min = min(cur_min, sum[i]);
75+
}
76+
free(sum);
77+
return result;
78+
}
79+
80+
/**
81+
* @brief 最大连续子序列和,动规
82+
* @param[in] S 数列
83+
* @param[in] n 数组的长度
84+
* @return 最大连续子序列和
85+
*/
86+
static int mcss_dp(int S[], int n) {
87+
int i, result;
88+
int *d = (int*) malloc(n * sizeof(int));
89+
d[0] = S[0];
90+
result = d[0];
91+
for (i = 1; i < n; i++) {
92+
d[i] = max(S[i], d[i - 1] + S[i]);
93+
if (result < d[i])
94+
result = d[i];
95+
}
96+
free(d);
97+
return result;
98+
}
99+
};
100+
\end{Code}
101+
102+
103+
\subsubsection{相关题目}
104+
\begindot
105+
\item Binary Tree Maximum Path Sum,见 \S \ref{sec:binary-tree-maximum-path-sum}
106+
\myenddot
107+
108+
4109
\section{Palindrome Partitioning II} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5110
\label{sec:palindrome-partitioning-ii}
6111

@@ -127,6 +232,115 @@ \subsubsection{代码}
127232

128233
\subsubsection{相关题目}
129234

235+
\begindot
236+
\item
237+
\myenddot
238+
239+
240+
\section{Best Time to Buy and Sell Stock III} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
241+
\label{sec:best-time-to-buy-and-sell-stock-iii}
242+
243+
244+
\subsubsection{描述}
245+
Say you have an array for which the i-th element is the price of a given stock on day i.
246+
247+
Design an algorithm to find the maximum profit. You may complete at most two transactions.
248+
249+
Note: You may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
250+
251+
252+
\subsubsection{分析}
253+
设状态$f(i)$,表示区间$[0,i](0 \leq i \leq n-1)$的最大利润,状态$g(i)$,表示区间$[i, n-1](0 \leq i \leq n-1)$的最大利润,则最终答案为$\max\left\{f(i)+g(i)\right\},0 \leq i \leq n-1$
254+
255+
允许在一天内买进又卖出,相当于不交易,因为题目的规定是最多两次,而不是一定要两次。
256+
257+
将原数组变成差分数组,本题也可以看做是最大$m$子段和,$m=2$,参考代码:\myurl{https://gist.github.com/soulmachine/5906637}
258+
259+
\subsubsection{代码}
260+
\begin{Code}
261+
// LeetCode, Best Time to Buy and Sell Stock III
262+
class Solution {
263+
public:
264+
int maxProfit(vector<int>& prices) {
265+
if (prices.size() < 2) return 0;
266+
267+
const int n = prices.size();
268+
vector<int> f(n, 0);
269+
vector<int> g(n, 0);
270+
271+
for (int i = 1, valley = prices[0]; i < n; ++i) {
272+
valley = std::min(valley, prices[i]);
273+
f[i] = std::max(f[i - 1], prices[i] - valley);
274+
}
275+
276+
for (int i = n - 2, peak = prices[n - 1]; i >= 0; --i) {
277+
peak = std::max(peak, prices[i]);
278+
g[i] = std::max(g[i], peak - prices[i]);
279+
}
280+
281+
int maxProfit = 0;
282+
for (int i = 0; i < n; ++i)
283+
maxProfit = max(maxProfit, f[i] + g[i]);
284+
285+
return maxProfit;
286+
}
287+
};
288+
\end{Code}
289+
290+
291+
\subsubsection{相关题目}
292+
\begindot
293+
\item Best Time to Buy and Sell Stock,见 \S \ref{sec:best-time-to-buy-and-sell-stock}
294+
\item Best Time to Buy and Sell Stock II,见 \S \ref{sec:best-time-to-buy-and-sell-stock-ii}
295+
\myenddot
296+
297+
298+
\section{Triangle} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
299+
\label{sec:triangle}
300+
301+
302+
\subsubsection{描述}
303+
Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.
304+
305+
For example, given the following triangle
306+
\begin{Code}
307+
[
308+
[2],
309+
[3,4],
310+
[6,5,7],
311+
[4,1,8,3]
312+
]
313+
\end{Code}
314+
The minimum path sum from top to bottom is 11 (i.e., 2 + 3 + 5 + 1 = 11).
315+
316+
Note: Bonus point if you are able to do this using only $O(n)$ extra space, where n is the total number of rows in the triangle.
317+
318+
319+
\subsubsection{分析}
320+
设状态为$f(i, j)$,表示从从位置$(i,j)$出发,路径的最小和,则状态转移方程为
321+
$$
322+
f(i,j)=\min\left\{f(i,j+1),f(i+1,j+1)\right\}+(i,j)
323+
$$
324+
325+
326+
\subsubsection{代码}
327+
\begin{Code}
328+
// LeetCode, Triangle
329+
class Solution {
330+
public:
331+
int minimumTotal (vector<vector<int>>& triangle) {
332+
for (int i = triangle.size() - 2; i >= 0; --i)
333+
for (int j = 0; j < i + 1; ++j)
334+
triangle[i][j] += std::min(triangle[i + 1][j],
335+
triangle[i + 1][j + 1]);
336+
337+
return triangle [0][0];
338+
}
339+
};
340+
\end{Code}
341+
342+
343+
\subsubsection{相关题目}
130344
\begindot
131345
\item
132346
\myenddot

C++/chapGreedy.tex

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
\chapter{贪心法}
2+
3+
4+
\section{Best Time to Buy and Sell Stock} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
5+
\label{sec:best-time-to-buy-and-sell-stock}
6+
7+
8+
\subsubsection{描述}
9+
Say you have an array for which the i-th element is the price of a given stock on day i.
10+
11+
If you were only permitted to complete at most one transaction (ie, buy one and sell one share of the stock), design an algorithm to find the maximum profit.
12+
13+
14+
\subsubsection{分析}
15+
贪心法,分别找到价格最低和最高的一天,低进高出,注意最低的一天要在最高的一天之前。
16+
17+
把原始价格序列变成差分序列,本题也可以做是最大$m$子段和,$m=1$
18+
19+
\subsubsection{代码}
20+
\begin{Code}
21+
class Solution {
22+
public:
23+
int maxProfit(vector<int> &prices) {
24+
if (prices.size() < 2) return 0;
25+
int profit = 0; // 差价,也就是利润
26+
int cur_min = prices[0]; // 当前最小
27+
28+
for (int i = 1; i < prices.size(); i++) {
29+
profit = std::max(profit, prices[i] - cur_min);
30+
cur_min = std::min(cur_min, prices[i]);
31+
}
32+
return profit;
33+
}
34+
};
35+
\end{Code}
36+
37+
38+
\subsubsection{相关题目}
39+
\begindot
40+
\item Best Time to Buy and Sell Stock II,见 \S \ref{sec:best-time-to-buy-and-sell-stock-ii}
41+
\item Best Time to Buy and Sell Stock III,见 \S \ref{sec:best-time-to-buy-and-sell-stock-iii}
42+
\myenddot
43+
44+
45+
\section{Best Time to Buy and Sell Stock II} %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
46+
\label{sec:best-time-to-buy-and-sell-stock-ii}
47+
48+
49+
\subsubsection{描述}
50+
Say you have an array for which the i-th element is the price of a given stock on day i.
51+
52+
Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times). However, you may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
53+
54+
55+
\subsubsection{分析}
56+
贪心法,低进高出,把所有正的价格差价相加起来。
57+
58+
把原始价格序列变成差分序列,本题也可以做是最大$m$子段和,$m=$数组长度。
59+
60+
\subsubsection{代码}
61+
\begin{Code}
62+
class Solution {
63+
public:
64+
int maxProfit(vector<int> &prices) {
65+
int sum = 0;
66+
for (int i = 1; i < prices.size(); i++) {
67+
int diff = prices[i] - prices[i - 1];
68+
if (diff > 0) sum += diff;
69+
}
70+
return sum;
71+
}
72+
};
73+
\end{Code}
74+
75+
76+
\subsubsection{相关题目}
77+
\begindot
78+
\item Best Time to Buy and Sell Stock,见 \S \ref{sec:best-time-to-buy-and-sell-stock}
79+
\item Best Time to Buy and Sell Stock III,见 \S \ref{sec:best-time-to-buy-and-sell-stock-iii}
80+
\myenddot

0 commit comments

Comments
 (0)