Skip to content

Commit ca0b530

Browse files
committed
重构
1 parent c6ae2ab commit ca0b530

File tree

6 files changed

+100
-73
lines changed

6 files changed

+100
-73
lines changed

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

2.39 KB
Binary file not shown.

C++/chapDFS.tex

Lines changed: 80 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,58 @@ \subsubsection{描述}
2323
\subsubsection{分析}
2424
在每一步都可以判断中间结果是否为合法结果,用回溯法。
2525

26-
一个长度为n的字符串,有n+1个地方可以砍断,每个地方可断可不断,因此复杂度为$O(2^{n+1})$
26+
一个长度为n的字符串,有n+1个地方可以砍断,每个地方可断可不断,前后两个隔板默认已经使用,因此复杂度为$O(2^{n-1})$
2727

2828

2929
\subsubsection{代码}
3030
\begin{Code}
3131
//LeetCode, Palindrome Partitioning
3232
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, 1, output, result);
38+
return result;
39+
}
40+
41+
// s[0, prev-1]之间已经处理,保证是回文串
42+
// prev 表示s[prev-1]与s[prev]之间的空隙位置,start同理
43+
void DFS(string &s, size_t prev, size_t start, vector<string>& output,
44+
vector<vector<string>> &result) {
45+
if (start == s.size()) { // 最后一个隔板
46+
if (isPalindrome(s, prev, start - 1)) { // 必须使用
47+
output.push_back(s.substr(prev, start - prev));
48+
result.push_back(output);
49+
output.pop_back();
50+
}
51+
return;
52+
}
53+
// 不断开
54+
DFS(s, prev, start + 1, output, result);
55+
// 如果[prev, start-1] 是回文,则可以断开,也可以不断开(上一行已经做了)
56+
if (isPalindrome(s, prev, start - 1)) {
57+
// 不断开,if 上一行已经做了
58+
// 断开
59+
output.push_back(s.substr(prev, start - prev));
60+
DFS(s, start, start + 1, output, result);
61+
output.pop_back();
62+
}
63+
}
64+
65+
bool isPalindrome(string &s, int start, int end) {
66+
while (start < end) {
67+
if (s[start++] != s[end--]) return false;
68+
}
69+
return true;
70+
}
71+
};
72+
\end{Code}
73+
74+
另一种写法,更加简洁。这种写法也在 Combination Sum, Combination Sum II 中出现过。
75+
\begin{Code}
76+
//LeetCode, Palindrome Partitioning
77+
class Solution {
3378
public:
3479
vector<vector<string>> partition(string s) {
3580
vector<vector<string>> result;
@@ -38,7 +83,6 @@ \subsubsection{代码}
3883
return result;
3984
}
4085
// 搜索必须以s[start]开头的partition方案
41-
// 如果一个字符串长度为n,则可以插入n+1个隔板,复制度为O(2^{n+1})
4286
void DFS(string &s, int start, vector<string>& output,
4387
vector<vector<string>> &result) {
4488
if (start == s.size()) {
@@ -101,20 +145,11 @@ \subsubsection{代码}
101145
class Solution {
102146
public:
103147
int uniquePaths(int m, int n) {
104-
this->m = m;
105-
this->n = n;
106-
return uniquePathsRecursive(m, n);
107-
}
108-
private:
109-
int m, n;
148+
if (m < 1 || n < 1) return 0; // 终止条件
110149

111-
int uniquePathsRecursive(int x, int y) {
112-
if (x < 1 || x > m) return 0; // 数据非法
113-
if (y < 1 || y > n) return 0;
150+
if (m == 1 && n == 1) return 1; // 收敛条件
114151

115-
if (x == 1 && y == 1) return 1; // 终止条件
116-
117-
return uniquePathsRecursive(x - 1, y) + uniquePathsRecursive(x, y - 1);
152+
return uniquePaths(m - 1, n) + uniquePaths(m, n - 1);
118153
}
119154
};
120155
\end{Code}
@@ -130,29 +165,24 @@ \subsubsection{代码}
130165
class Solution {
131166
public:
132167
int uniquePaths(int m, int n) {
133-
this->m = m;
134-
this->n = n;
135168
// 0行和0列未使用
136169
this->f = vector<vector<int> >(m + 1, vector<int>(n + 1, 0));
137-
return cachedUniquePathsRecursive(m, n);
170+
return dfs(m, n);
138171
}
139172
private:
140-
int m, n; // 全局只读数据
141173
vector<vector<int> > f; // 缓存
142174

143-
int uniquePathsRecursive(int x, int y) {
144-
if (x < 1 || x > m) return 0; // 数据非法,终止条件
145-
if (y < 1 || y > n) return 0;
175+
int dfs(int x, int y) {
176+
if (x < 1 || y < 1) return 0; // 数据非法,终止条件
146177

147178
if (x == 1 && y == 1) return 1; // 回到起点,收敛条件
148179

149-
return cachedUniquePathsRecursive(x - 1, y) +
150-
cachedUniquePathsRecursive(x, y - 1);
180+
return getOrUpdate(x - 1, y) + getOrUpdate(x, y - 1);
151181
}
152182

153-
int cachedUniquePathsRecursive(int x, int y) {
183+
int getOrUpdate(int x, int y) {
154184
if (f[x][y] > 0) return f[x][y];
155-
else return f[x][y] = uniquePathsRecursive(x, y);
185+
else return f[x][y] = dfs(x, y);
156186
}
157187
};
158188
\end{Code}
@@ -272,29 +302,28 @@ \subsubsection{代码}
272302
const int n = obstacleGrid[0].size();
273303
// 0行和0列未使用
274304
this->f = vector<vector<int> >(m + 1, vector<int>(n + 1, 0));
275-
return cachedUniquePathsRecursive(obstacleGrid, m, n);
305+
return dfs(obstacleGrid, m, n);
276306
}
277307
private:
278308
vector<vector<int> > f; // 缓存
279309

280-
int uniquePathsRecursive(const vector<vector<int> > &obstacleGrid,
310+
int dfs(const vector<vector<int> > &obstacleGrid,
281311
int x, int y) {
282-
if (x < 1 || x > obstacleGrid.size()) return 0; // 数据非法,终止条件
283-
if (y < 1 || y > obstacleGrid[0].size()) return 0;
312+
if (x < 1 || y < 1) return 0; // 数据非法,终止条件
284313

285314
// (x,y)是障碍
286315
if (obstacleGrid[x-1][y-1]) return 0;
287316

288317
if (x == 1 and y == 1) return 1; // 回到起点,收敛条件
289318

290-
return cachedUniquePathsRecursive(obstacleGrid, x - 1, y) +
291-
cachedUniquePathsRecursive(obstacleGrid, x, y - 1);
319+
return getOrUpdate(obstacleGrid, x - 1, y) +
320+
getOrUpdate(obstacleGrid, x, y - 1);
292321
}
293322

294-
int cachedUniquePathsRecursive(const vector<vector<int> > &obstacleGrid,
323+
int getOrUpdate(const vector<vector<int> > &obstacleGrid,
295324
int x, int y) {
296325
if (f[x][y] > 0) return f[x][y];
297-
else return f[x][y] = uniquePathsRecursive(obstacleGrid, x, y);
326+
else return f[x][y] = dfs(obstacleGrid, x, y);
298327
}
299328
};
300329
\end{Code}
@@ -401,7 +430,7 @@ \subsubsection{代码}
401430

402431
vector<vector<string> > result;
403432
vector<int> C(n, 0); // C[i]表示第i行皇后所在的列编号
404-
solveNQueens(0, C, result);
433+
dfs(0, C, result);
405434
return result;
406435
}
407436
private:
@@ -410,7 +439,7 @@ \subsubsection{代码}
410439
vector<int> principal_diagonals; // 占据了哪些主对角线
411440
vector<int> counter_diagonals; // 占据了哪些副对角线
412441

413-
void solveNQueens(int row, vector<int> &C,
442+
void dfs(int row, vector<int> &C,
414443
vector<vector<string> > &result) {
415444
const int N = C.size();
416445
if (row == N) { // 终止条件,也是收敛条件,意味着找到了一个可行解
@@ -435,7 +464,7 @@ \subsubsection{代码}
435464
C[row] = j;
436465
columns[j] = principal_diagonals[row + j] =
437466
counter_diagonals[row - j + N] = 1;
438-
solveNQueens(row + 1, C, result);
467+
dfs(row + 1, C, result);
439468
// 撤销动作
440469
// C[row] = 0;
441470
columns[j] = principal_diagonals[row + j] =
@@ -479,9 +508,8 @@ \subsubsection{代码}
479508
this->principal_diagonals = vector<int>(2 * n, 0);
480509
this->counter_diagonals = vector<int>(2 * n, 0);
481510

482-
vector<vector<string> > result;
483511
vector<int> C(n, 0); // C[i]表示第i行皇后所在的列编号
484-
solveNQueens(0, C, result);
512+
dfs(0, C);
485513
return this->count;
486514
}
487515
private:
@@ -491,8 +519,7 @@ \subsubsection{代码}
491519
vector<int> principal_diagonals; // 占据了哪些主对角线
492520
vector<int> counter_diagonals; // 占据了哪些副对角线
493521

494-
void solveNQueens(int row, vector<int> &C,
495-
vector<vector<string> > &result) {
522+
void dfs(int row, vector<int> &C) {
496523
const int N = C.size();
497524
if (row == N) { // 终止条件,也是收敛条件,意味着找到了一个可行解
498525
this->count++;
@@ -508,7 +535,7 @@ \subsubsection{代码}
508535
C[row] = j;
509536
columns[j] = principal_diagonals[row + j] =
510537
counter_diagonals[row - j + N] = 1;
511-
solveNQueens(row + 1, C, result);
538+
dfs(row + 1, C);
512539
// 撤销动作
513540
// C[row] = 0;
514541
columns[j] = principal_diagonals[row + j] =
@@ -564,21 +591,21 @@ \subsubsection{代码}
564591
* @param[out] result 存放所有可能的IP地址
565592
* @return 无
566593
*/
567-
void dfs(string s, int start, int step, string ip,
594+
void dfs(string s, size_t start, size_t step, string ip,
568595
vector<string> &result) {
569-
if (s.size() - start > (4 - step) * 3)
570-
return; // 非法结果,剪枝
571-
if (s.size() - start < (4 - step))
572-
return; // 非法结果,剪枝
573-
574596
if (start == s.size() && step == 4) { // 找到一个合法解
575597
ip.resize(ip.size() - 1);
576598
result.push_back(ip);
577599
return;
578600
}
579601

602+
if (s.size() - start > (4 - step) * 3)
603+
return; // 剪枝
604+
if (s.size() - start < (4 - step))
605+
return; // 剪枝
606+
580607
int num = 0;
581-
for (int i = start; i < start + 3; i++) {
608+
for (size_t i = start; i < start + 3; i++) {
582609
num = num * 10 + (s[i] - '0');
583610

584611
if (num <= 255) { // 当前结点合法,则继续往下递归
@@ -640,13 +667,13 @@ \subsubsection{代码}
640667
}
641668

642669
private:
643-
void dfs(vector<int>& nums, int gap, int level, vector<int>& intermediate,
670+
void dfs(vector<int>& nums, int gap, int start, vector<int>& intermediate,
644671
vector<vector<int> > &result) {
645672
if (gap == 0) { // 找到一个合法解
646673
result.push_back(intermediate);
647674
return;
648675
}
649-
for (size_t i = level; i < nums.size(); i++) { // 扩展状态
676+
for (size_t i = start; i < nums.size(); i++) { // 扩展状态
650677
if (gap < nums[i]) return; // 剪枝
651678

652679
intermediate.push_back(nums[i]); // 执行扩展动作
@@ -708,16 +735,16 @@ \subsubsection{代码}
708735
return result;
709736
}
710737
private:
711-
// 使用nums[index, nums.size())之间的元素,能找到的所有可行解
712-
static void dfs(vector<int> &nums, int gap, int index,
738+
// 使用nums[start, nums.size())之间的元素,能找到的所有可行解
739+
static void dfs(vector<int> &nums, int gap, int start,
713740
vector<int> &intermediate, vector<vector<int> > &result) {
714741
if (gap == 0) { // 找到一个合法解
715742
result.push_back(intermediate);
716743
return;
717744
}
718745

719746
int previous = -1;
720-
for (size_t i = index; i < nums.size(); i++) {
747+
for (size_t i = start; i < nums.size(); i++) {
721748
// 如果上一轮循环没有选nums[i],则本次循环就不能再选nums[i],
722749
// 确保nums[i]最多只用一次
723750
if (previous == nums[i]) continue;

C++/chapDivideAndConquer.tex

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,18 @@ \subsubsection{代码}
1818
//LeetCode, Pow(x, n)
1919
// 二分法,$x^n = x^{n/2} * x^{n/2} * x^{n\%2}$
2020
class Solution {
21+
public:
22+
double pow(double x, int n) {
23+
if (n < 0) return 1.0 / power(x, -n);
24+
else return power(x, n);
25+
}
2126
private:
2227
double power(double x, int n) {
2328
if (n == 0) return 1;
2429
double v = power(x, n / 2);
2530
if (n % 2 == 0) return v * v;
2631
else return v * v * x;
2732
}
28-
public:
29-
double pow(double x, int n) {
30-
if (n < 0) return 1.0 / power(x, -n);
31-
else return power(x, n);
32-
}
3333
};
3434
\end{Code}
3535

C++/chapDynamicProgramming.tex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -329,11 +329,11 @@ \subsubsection{代码}
329329
g[i] = max(g[i], peak - prices[i]);
330330
}
331331

332-
int maxProfit = 0;
332+
int max_profit = 0;
333333
for (int i = 0; i < n; ++i)
334-
maxProfit = max(maxProfit, f[i] + g[i]);
334+
max_profit = max(max_profit, f[i] + g[i]);
335335

336-
return maxProfit;
336+
return max_profit;
337337
}
338338
};
339339
\end{Code}

C++/chapGreedy.tex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ \subsubsection{代码}
127127

128128
while (left <= right) { // 尝试从每一层跳最远
129129
++step;
130-
int old_right = right;
130+
const int old_right = right;
131131
for (int i = left; i <= old_right; ++i) {
132132
int new_right = i + A[i];
133133
if (new_right >= n - 1) return step;

C++/chapImplement.tex

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -287,18 +287,20 @@ \subsubsection{代码}
287287
\begin{Code}
288288
// LeetCode, Multiply Strings
289289
// 一个字符对应一个int
290-
typedef vector<char> bigint;
290+
typedef vector<int> bigint;
291291

292292
bigint make_bigint(string const& repr) {
293293
bigint n;
294-
transform(repr.rbegin(), repr.rend(), back_inserter(n), [](char c) { return c - '0'; });
294+
transform(repr.rbegin(), repr.rend(), back_inserter(n),
295+
[](char c) { return c - '0'; });
295296
return move(n);
296297
}
297298

298299
string to_string(bigint const& n) {
299300
string str;
300-
transform(find_if(n.rbegin(), prev(n.rend()), [](char c) { return c > '\0'; }),
301-
n.rend(), back_inserter(str), [](char c) { return c + '0'; });
301+
transform(find_if(n.rbegin(), prev(n.rend()),
302+
[](char c) { return c > '\0'; }), n.rend(), back_inserter(str),
303+
[](char c) { return c + '0'; });
302304
return move(str);
303305
}
304306

@@ -527,13 +529,13 @@ \subsubsection{代码}
527529
result.push_back(vector<int>(1,1)); //first row
528530

529531
for(int i = 2; i <= numRows; ++i) {
530-
vector<int> thisrow(i,1); // 本行
531-
vector<int> &lastrow = result[i-2]; // 上一行
532+
vector<int> current(i,1); // 本行
533+
const vector<int> &prev = result[i-2]; // 上一行
532534

533535
for(int j = 1; j < i - 1; ++j) {
534-
thisrow[j] = lastrow[j-1] + lastrow[j]; // 左上角和右上角之和
536+
current[j] = prev[j-1] + prev[j]; // 左上角和右上角之和
535537
}
536-
result.push_back(thisrow);
538+
result.push_back(current);
537539
}
538540
return result;
539541
}
@@ -573,9 +575,7 @@ \subsubsection{代码}
573575
class Solution {
574576
public:
575577
vector<int> getRow(int rowIndex) {
576-
vector<int> result;
577-
result.resize(rowIndex + 2);
578-
result.assign(result.size(), 0);
578+
vector<int> result(rowIndex + 2, 0);
579579

580580
result[1] = 1;
581581
for (int i = 0; i < rowIndex; i++) {

0 commit comments

Comments
 (0)