@@ -23,13 +23,58 @@ \subsubsection{描述}
23
23
\subsubsection {分析 }
24
24
在每一步都可以判断中间结果是否为合法结果,用回溯法。
25
25
26
- 一个长度为n的字符串,有n+1个地方可以砍断,每个地方可断可不断,因此复杂度为$ O(2 ^{n+ 1})$
26
+ 一个长度为n的字符串,有n+1个地方可以砍断,每个地方可断可不断,前后两个隔板默认已经使用, 因此复杂度为$ O(2 ^{n- 1})$
27
27
28
28
29
29
\subsubsection {代码 }
30
30
\begin {Code }
31
31
//LeetCode, Palindrome Partitioning
32
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, 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 {
33
78
public:
34
79
vector<vector<string>> partition(string s) {
35
80
vector<vector<string>> result;
@@ -38,7 +83,6 @@ \subsubsection{代码}
38
83
return result;
39
84
}
40
85
// 搜索必须以s[start]开头的partition方案
41
- // 如果一个字符串长度为n,则可以插入n+1个隔板,复制度为O(2^{n+1})
42
86
void DFS(string &s, int start, vector<string>& output,
43
87
vector<vector<string>> &result) {
44
88
if (start == s.size()) {
@@ -101,20 +145,11 @@ \subsubsection{代码}
101
145
class Solution {
102
146
public:
103
147
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; // 终止条件
110
149
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; // 收敛条件
114
151
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);
118
153
}
119
154
};
120
155
\end {Code }
@@ -130,29 +165,24 @@ \subsubsection{代码}
130
165
class Solution {
131
166
public:
132
167
int uniquePaths(int m, int n) {
133
- this->m = m;
134
- this->n = n;
135
168
// 0行和0列未使用
136
169
this->f = vector<vector<int> >(m + 1, vector<int>(n + 1, 0));
137
- return cachedUniquePathsRecursive (m, n);
170
+ return dfs (m, n);
138
171
}
139
172
private:
140
- int m, n; // 全局只读数据
141
173
vector<vector<int> > f; // 缓存
142
174
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; // 数据非法,终止条件
146
177
147
178
if (x == 1 && y == 1) return 1; // 回到起点,收敛条件
148
179
149
- return cachedUniquePathsRecursive(x - 1, y) +
150
- cachedUniquePathsRecursive(x, y - 1);
180
+ return getOrUpdate(x - 1, y) + getOrUpdate(x, y - 1);
151
181
}
152
182
153
- int cachedUniquePathsRecursive (int x, int y) {
183
+ int getOrUpdate (int x, int y) {
154
184
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);
156
186
}
157
187
};
158
188
\end {Code }
@@ -272,29 +302,28 @@ \subsubsection{代码}
272
302
const int n = obstacleGrid[0].size();
273
303
// 0行和0列未使用
274
304
this->f = vector<vector<int> >(m + 1, vector<int>(n + 1, 0));
275
- return cachedUniquePathsRecursive (obstacleGrid, m, n);
305
+ return dfs (obstacleGrid, m, n);
276
306
}
277
307
private:
278
308
vector<vector<int> > f; // 缓存
279
309
280
- int uniquePathsRecursive (const vector<vector<int> > &obstacleGrid,
310
+ int dfs (const vector<vector<int> > &obstacleGrid,
281
311
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; // 数据非法,终止条件
284
313
285
314
// (x,y)是障碍
286
315
if (obstacleGrid[x-1][y-1]) return 0;
287
316
288
317
if (x == 1 and y == 1) return 1; // 回到起点,收敛条件
289
318
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);
292
321
}
293
322
294
- int cachedUniquePathsRecursive (const vector<vector<int> > &obstacleGrid,
323
+ int getOrUpdate (const vector<vector<int> > &obstacleGrid,
295
324
int x, int y) {
296
325
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);
298
327
}
299
328
};
300
329
\end {Code }
@@ -401,7 +430,7 @@ \subsubsection{代码}
401
430
402
431
vector<vector<string> > result;
403
432
vector<int> C(n, 0); // C[i]表示第i行皇后所在的列编号
404
- solveNQueens (0, C, result);
433
+ dfs (0, C, result);
405
434
return result;
406
435
}
407
436
private:
@@ -410,7 +439,7 @@ \subsubsection{代码}
410
439
vector<int> principal_diagonals; // 占据了哪些主对角线
411
440
vector<int> counter_diagonals; // 占据了哪些副对角线
412
441
413
- void solveNQueens (int row, vector<int> &C,
442
+ void dfs (int row, vector<int> &C,
414
443
vector<vector<string> > &result) {
415
444
const int N = C.size();
416
445
if (row == N) { // 终止条件,也是收敛条件,意味着找到了一个可行解
@@ -435,7 +464,7 @@ \subsubsection{代码}
435
464
C[row] = j;
436
465
columns[j] = principal_diagonals[row + j] =
437
466
counter_diagonals[row - j + N] = 1;
438
- solveNQueens (row + 1, C, result);
467
+ dfs (row + 1, C, result);
439
468
// 撤销动作
440
469
// C[row] = 0;
441
470
columns[j] = principal_diagonals[row + j] =
@@ -479,9 +508,8 @@ \subsubsection{代码}
479
508
this->principal_diagonals = vector<int>(2 * n, 0);
480
509
this->counter_diagonals = vector<int>(2 * n, 0);
481
510
482
- vector<vector<string> > result;
483
511
vector<int> C(n, 0); // C[i]表示第i行皇后所在的列编号
484
- solveNQueens (0, C, result );
512
+ dfs (0, C);
485
513
return this->count;
486
514
}
487
515
private:
@@ -491,8 +519,7 @@ \subsubsection{代码}
491
519
vector<int> principal_diagonals; // 占据了哪些主对角线
492
520
vector<int> counter_diagonals; // 占据了哪些副对角线
493
521
494
- void solveNQueens(int row, vector<int> &C,
495
- vector<vector<string> > &result) {
522
+ void dfs(int row, vector<int> &C) {
496
523
const int N = C.size();
497
524
if (row == N) { // 终止条件,也是收敛条件,意味着找到了一个可行解
498
525
this->count++;
@@ -508,7 +535,7 @@ \subsubsection{代码}
508
535
C[row] = j;
509
536
columns[j] = principal_diagonals[row + j] =
510
537
counter_diagonals[row - j + N] = 1;
511
- solveNQueens (row + 1, C, result );
538
+ dfs (row + 1, C);
512
539
// 撤销动作
513
540
// C[row] = 0;
514
541
columns[j] = principal_diagonals[row + j] =
@@ -564,21 +591,21 @@ \subsubsection{代码}
564
591
* @param[out] result 存放所有可能的IP地址
565
592
* @return 无
566
593
*/
567
- void dfs(string s, int start, int step, string ip,
594
+ void dfs(string s, size_t start, size_t step, string ip,
568
595
vector<string> &result) {
569
- if (s.size() - start > (4 - step) * 3)
570
- return; // 非法结果,剪枝
571
- if (s.size() - start < (4 - step))
572
- return; // 非法结果,剪枝
573
-
574
596
if (start == s.size() && step == 4) { // 找到一个合法解
575
597
ip.resize(ip.size() - 1);
576
598
result.push_back(ip);
577
599
return;
578
600
}
579
601
602
+ if (s.size() - start > (4 - step) * 3)
603
+ return; // 剪枝
604
+ if (s.size() - start < (4 - step))
605
+ return; // 剪枝
606
+
580
607
int num = 0;
581
- for (int i = start; i < start + 3; i++) {
608
+ for (size_t i = start; i < start + 3; i++) {
582
609
num = num * 10 + (s[i] - '0' );
583
610
584
611
if (num <= 255) { // 当前结点合法,则继续往下递归
@@ -640,13 +667,13 @@ \subsubsection{代码}
640
667
}
641
668
642
669
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,
644
671
vector<vector<int> > &result) {
645
672
if (gap == 0) { // 找到一个合法解
646
673
result.push_back(intermediate);
647
674
return;
648
675
}
649
- for (size_t i = level ; i < nums.size(); i++) { // 扩展状态
676
+ for (size_t i = start ; i < nums.size(); i++) { // 扩展状态
650
677
if (gap < nums[i]) return; // 剪枝
651
678
652
679
intermediate.push_back(nums[i]); // 执行扩展动作
@@ -708,16 +735,16 @@ \subsubsection{代码}
708
735
return result;
709
736
}
710
737
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 ,
713
740
vector<int> &intermediate, vector<vector<int> > &result) {
714
741
if (gap == 0) { // 找到一个合法解
715
742
result.push_back(intermediate);
716
743
return;
717
744
}
718
745
719
746
int previous = -1;
720
- for (size_t i = index ; i < nums.size(); i++) {
747
+ for (size_t i = start ; i < nums.size(); i++) {
721
748
// 如果上一轮循环没有选nums[i],则本次循环就不能再选nums[i],
722
749
// 确保nums[i]最多只用一次
723
750
if (previous == nums[i]) continue;
0 commit comments