Skip to content

Commit 7222ec6

Browse files
committed
新增部分DP算法
1 parent 3fe6a59 commit 7222ec6

File tree

13 files changed

+593
-223
lines changed

13 files changed

+593
-223
lines changed

README.md

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
| 1| [两数之和](https://leetcode-cn.com/problems/two-sum/) | [twoSum](./array/leetcode/easy/twoSum.h) | <font color=green>easy</font> ||
66
| 2| [两数相加](https://leetcode-cn.com/problems/add-two-numbers/) | [addTwoNumbers](./linkedList/leetcode/medium/addTwoNumbers.h) | <font color=orange> medium </font> ||
77
| 3| [无重复字符的最长子串](https://leetcode-cn.com/problems/longest-substring-without-repeating-characters/) | [lengthOfLongestSubstring](./string/leetcode/medium/lengthOfLongestSubstring.h) | <font color=orange> medium </font> ||
8-
| 5| [最长回文子串](https://leetcode-cn.com/problems/longest-palindromic-substring/) | [longestPalindrome](./string/leetcode/medium/longestPalindrome.h) | <font color=orange> medium </font>[需要回看其他解法] ||
8+
| 5| [最长回文子串](https://leetcode-cn.com/problems/longest-palindromic-substring/) | [longestPalindrome](./string/leetcode/medium/longestPalindrome.h) | <font color=orange> medium </font>||
99
| 6| [Z字形变换](https://leetcode-cn.com/problems/zigzag-conversion/) | [zigzag_conversion](./string/leetcode/medium/zigzag_conversion.h) | <font color=orange> medium </font>||
1010
| 7| [整数反转](https://leetcode-cn.com/problems/reverse-integer/) | [reverse_integer](./other/leetcode/easy/reverse_integer.h) | <font color=green>easy</font> ||
1111
| 8| [字符串转换整数 (atoi)](https://leetcode-cn.com/problems/string-to-integer-atoi/) | [string_to_integer_atoi](./string/leetcode/medium/string_to_integer_atoi.h) | <font color=orange> medium </font> ||
@@ -106,10 +106,10 @@
106106
回溯算法是”万金油“。基本上贪心和dp能解决的问题,回溯都能解决。回溯相当于穷举搜索,列举出所有的情况,然后对比得到最优解。不过回溯的复杂度一般都是指数级的,只能用来解决小规模数据的问题。-->
107107

108108

109-
## [贪心](./greed.md)🚶🚶🚶🚶❌
110-
## [回溯算法](./backtracking.md)
111-
## [分治算法](./divideandconquer.md)
112-
## [动态规划](./dp.md)
109+
## [贪心](./greed.md)
110+
## [回溯算法](./backtracking.md)
111+
## [分治算法](./divideandconquer.md)🚶🚶🚶🚶
112+
## [动态规划](./dp.md)
113113

114114

115115
## [字符串匹配](./stringmatch.md)
@@ -127,27 +127,6 @@
127127

128128
## [数组](./array.md)
129129

130-
数组有两个关键词:
131-
132-
* 线性表结构, 就是说元素之间只有前后关系
133-
* 连续的内存空间,存储的是具有相同类型的数据
134-
135-
第二个特征决定了数组<font size=5 color=red>“随机访问”</font>的能力,因为我们完全可以通过地址计算出下标对应的位置。比如:
136-
137-
<font size=5>a[i]_add = base_add + i * type_size</font>
138-
139-
有利就有弊,也正是由于内存连续,所以数组的插入和删除是非常低效的,因为为了保持内存的连续,就意味着每次插入/删除都要伴随着<font size=5 color=red>大量的移动操作</font>,平均负责度为o(n).
140-
141-
142-
<font size=5 color=red>容器类</font>在数组的基础上,封装了插入删除等操作,同时支持了动态扩容. 需要注意的是,如果实现知道数组的大小,最好提前指定容器大小,这样可以省掉多次的内存申请和数据搬移。
143-
144-
大多情况下的<font size=5 color=red>解题思路</font>:
145-
146-
* 双指针
147-
* DP
148-
* 二分查找
149-
150-
151130
## [链表](./linkedList.md)
152131
## [栈&队列](./stack_queue.md)
153132

alg-cpp.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,8 @@
193193
09421FFA23142AEB00A7BA67 /* searchRange.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = searchRange.h; sourceTree = "<group>"; };
194194
09421FFD231583FC00A7BA67 /* isValidSudoku.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = isValidSudoku.h; sourceTree = "<group>"; };
195195
0942542C232942D3006B83E9 /* gas_station.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = gas_station.h; sourceTree = "<group>"; };
196+
094524B7234790CD00CCBFB9 /* coinChange.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = coinChange.h; sourceTree = "<group>"; };
197+
094524BA234A32D000CCBFB9 /* levenshtein_distance.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = levenshtein_distance.h; sourceTree = "<group>"; };
196198
0946B01522F68BA50043469D /* FirstNotRepeatingChar.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FirstNotRepeatingChar.h; sourceTree = "<group>"; };
197199
0946B01822F695CE0043469D /* ReverseSentence.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReverseSentence.h; sourceTree = "<group>"; };
198200
0946B01B22F6A5BF0043469D /* StrToInt.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StrToInt.h; sourceTree = "<group>"; };
@@ -224,6 +226,7 @@
224226
0965B3CE23045B1C009A153E /* addBinary.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = addBinary.h; sourceTree = "<group>"; };
225227
0965B3D223046663009A153E /* climbStairs.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = climbStairs.h; sourceTree = "<group>"; };
226228
0965B3D523046775009A153E /* romanToInt.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = romanToInt.h; sourceTree = "<group>"; };
229+
09665E9C234CD7ED003D0FAE /* pascals_triangle.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = pascals_triangle.h; sourceTree = "<group>"; };
227230
0969A71B22E607E800CA9347 /* string */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = string; sourceTree = BUILT_PRODUCTS_DIR; };
228231
0969A71D22E607E800CA9347 /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; };
229232
0969A72222E6081500CA9347 /* matching.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = matching.h; sourceTree = "<group>"; };
@@ -290,6 +293,7 @@
290293
09FC39212305A42B00F0A2AE /* addTwoNumbers.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = addTwoNumbers.h; sourceTree = "<group>"; };
291294
09FC39252305A9A500F0A2AE /* lengthOfLongestSubstring.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = lengthOfLongestSubstring.h; sourceTree = "<group>"; };
292295
09FC39282305B35900F0A2AE /* longestPalindrome.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = longestPalindrome.h; sourceTree = "<group>"; };
296+
3A04E7432341F1B7006770AF /* double11advance.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = double11advance.h; sourceTree = "<group>"; };
293297
3A091A2C22EFE34800EFA79C /* inorderTraversal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = inorderTraversal.h; sourceTree = "<group>"; };
294298
3A091A2F22EFE62E00EFA79C /* isValidBST.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = isValidBST.h; sourceTree = "<group>"; };
295299
3A091A3222F0450400EFA79C /* invertTree.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = invertTree.h; sourceTree = "<group>"; };
@@ -708,6 +712,10 @@
708712
3AD40CDC22EAF129002D60A6 /* leetcode */,
709713
0998EB8C22E75FB9005A01B5 /* main.cpp */,
710714
0998EB9122E75FEC005A01B5 /* knapsack.h */,
715+
094524B7234790CD00CCBFB9 /* coinChange.h */,
716+
3A04E7432341F1B7006770AF /* double11advance.h */,
717+
094524BA234A32D000CCBFB9 /* levenshtein_distance.h */,
718+
09665E9C234CD7ED003D0FAE /* pascals_triangle.h */,
711719
);
712720
path = dp;
713721
sourceTree = "<group>";
1.67 KB
Binary file not shown.
7.91 KB
Binary file not shown.

alg-cpp.xcodeproj/xcuserdata/junl.xcuserdatad/xcschemes/xcschememanagement.plist

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -22,22 +22,22 @@
2222
<key>base.xcscheme_^#shared#^_</key>
2323
<dict>
2424
<key>orderHint</key>
25-
<integer>7</integer>
25+
<integer>5</integer>
2626
</dict>
2727
<key>bsearch.xcscheme_^#shared#^_</key>
2828
<dict>
2929
<key>orderHint</key>
30-
<integer>8</integer>
30+
<integer>9</integer>
3131
</dict>
3232
<key>divideandconquer.xcscheme_^#shared#^_</key>
3333
<dict>
3434
<key>orderHint</key>
35-
<integer>13</integer>
35+
<integer>14</integer>
3636
</dict>
3737
<key>dp.xcscheme_^#shared#^_</key>
3838
<dict>
3939
<key>orderHint</key>
40-
<integer>10</integer>
40+
<integer>12</integer>
4141
</dict>
4242
<key>greed.xcscheme_^#shared#^_</key>
4343
<dict>
@@ -47,12 +47,12 @@
4747
<key>hasTable.xcscheme_^#shared#^_</key>
4848
<dict>
4949
<key>orderHint</key>
50-
<integer>11</integer>
50+
<integer>10</integer>
5151
</dict>
5252
<key>linkedList.xcscheme_^#shared#^_</key>
5353
<dict>
5454
<key>orderHint</key>
55-
<integer>9</integer>
55+
<integer>6</integer>
5656
</dict>
5757
<key>other.xcscheme_^#shared#^_</key>
5858
<dict>
@@ -62,17 +62,17 @@
6262
<key>recursion.xcscheme_^#shared#^_</key>
6363
<dict>
6464
<key>orderHint</key>
65-
<integer>14</integer>
65+
<integer>13</integer>
6666
</dict>
6767
<key>sort.xcscheme_^#shared#^_</key>
6868
<dict>
6969
<key>orderHint</key>
70-
<integer>5</integer>
70+
<integer>8</integer>
7171
</dict>
7272
<key>stack+queue.xcscheme_^#shared#^_</key>
7373
<dict>
7474
<key>orderHint</key>
75-
<integer>6</integer>
75+
<integer>7</integer>
7676
</dict>
7777
<key>string.xcscheme_^#shared#^_</key>
7878
<dict>
@@ -82,7 +82,7 @@
8282
<key>tree.xcscheme_^#shared#^_</key>
8383
<dict>
8484
<key>orderHint</key>
85-
<integer>12</integer>
85+
<integer>11</integer>
8686
</dict>
8787
</dict>
8888
<key>SuppressBuildableAutocreation</key>

divideandconquer.md

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,27 @@
1-
## 分治算法
1+
# 分治算法
22

3-
### <font color=red>经典题型</font>
3+
分治算法的核心思想就是分而治之。将原问题划分成n个规模较小,并且结构与原问题相似的子问题,然后递归的求解这些子问题,再将子问题的解合并成结果,就得到了原问题的解。
4+
5+
6+
分治算法能解决的问题,一般要满足下面几个条件:
7+
8+
1. 原问题和分解的小问题具有相同的求解模式.
9+
2. 分解的子问题可以独立求解,子问题之间没有任何关联,这是分治和动态规划最明显的区别
10+
3. 具有分解的终止条件,也就是说当问题足够小时,可以直接求解.
11+
4. 可以将子问题的求解合并成原问题,而这个合并操作的复杂度不能太高,否则就起不到减少算法总体的复杂度恶效果了。
12+
13+
14+
15+
16+
## <font color=red>经典题型</font>
417

518

619
| &emsp;题型&emsp; | 答案链接 | 完成度 |
720
| :--: | :----------------------------------------------------------- | :--------: |
8-
| 求一组数据里面的逆序对 | [reversedOrderPairs](./divideConquer/reversedOrderPairs.h)||
9-
| 二维平面上有n个点,如何快速求出最近的两个点之间的距离 | [closestPair](./divideConquer/closestPair.h)||
21+
| 求一组数据里面的逆序对 | [reversedOrderPairs](./divideandconquer/reversedOrderPairs.h)||
22+
| 二维平面上有n个点,如何快速求出最近的两个点之间的距离 | [closestPair](./divideandconquer/closestPair.h)||
1023

11-
### leetcode
24+
## leetcode
1225
| &emsp;题号&emsp; | 题目链接&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;| 答案链接&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;&emsp;| &emsp;难度&emsp; | &emsp;完成度&emsp; |
1326
| :--: | :--: | :----------------------------------------------------------- | :----------------------------------------------------------- | :------: |
1427
| 17 | [电话号码的字母组合](https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number/)| --| ✨✨ ||

dp.md

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,29 @@
1-
## 动态规划
1+
# 动态规划
2+
3+
4+
5+
我们把问题的求解分成N个阶段,每个阶段对应一次选择,每次选择之后,会产生不同的状态,我们记录每个阶段的这些状态。然后通过当前的状态集合推导出下一阶段的状态集合,动态的向前推进。
6+
7+
就拿0-1背包问题来说,回溯和动态规划都能解决这个问题。只不过回溯算法解决起来的效率是很低的,时间复杂度是指数级别的,而动态规划在执行效率方面就提高很多,尽管执行效率提高了,但是动态规划的空间复杂度也提高了,所以很多时候我们会说动态规划是一种空间换时间的算法。
8+
9+
10+
11+
## 什么样的问题适合使用动态规划来解决?
12+
13+
14+
动态规划适合用于<font size=5 color=red>多阶段决策最优解模型</font>, 就是说动态规划一般是用来解决最优解问题,而解决问题的过程需要经历多个阶段,每个阶段决策之后会对应一组状态,然后我们寻找一组决策序列,经过这组决策序列,最终求出问题的最优解。
15+
16+
217

318

419
### <font color=red>经典题型</font>
520

621
| &emsp;题型&emsp; | 答案链接 | 完成度 |
722
| :--: | :----------------------------------------------------------- | :--------: |
823
| 0-1背包问题及变种 | [knapsack](./dp/knapsack.h)||
9-
| 双11打折优惠问题 | [double11advance](./dp/knapsack.h)||
10-
| 硬币找零问题 | [coinChange2](./dp/knapsack.h)||
24+
| 双11打折优惠问题 | [double11advance](./dp/double11advance.h)||
25+
| 硬币找零问题 | [coinChange2](./dp/coinChange.h)||
26+
| 杨辉三角变种 | [pascals_triangle](./dp/pascals_triangle.h)||
1127
| 莱文斯坦最短编辑距离 | -- ||
1228
| 两个字符串的最长公共子序列 | -- ||
1329
| 数据序列的最长递增子序列 | -- ||

dp/coinChange.h

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
//
2+
// coinChange.h
3+
// dp
4+
//
5+
// Created by junl on 2019/10/4.
6+
// Copyright © 2019 junl. All rights reserved.
7+
//
8+
9+
#ifndef coinChange_hpp
10+
#define coinChange_hpp
11+
12+
#include <stdio.h>
13+
/*
14+
硬币找零问题。比如我们现在有硬币1元,3元,5元,我们需要支付w元,那么最少需要多少个硬币.
15+
思路:
16+
1. 贪心法,每次首先尝试最大面值的币种
17+
*/
18+
class coinChange {
19+
public:
20+
//贪心法,首先尝试最大面值的币种
21+
void solve(const int coins[], int n, int money, int currentCoinCount){
22+
if (money == 0 || currentCoinCount == n) {
23+
result = std::min(result, currentCoinCount);
24+
return;
25+
}
26+
for (int i=n-1; i>=0; i--) {
27+
if (money >= coins[i]) {
28+
solve(coins, n, money - coins[i], currentCoinCount+1);
29+
}
30+
}
31+
32+
}
33+
int solve(const int coins[], int n, int money){
34+
solve(coins, n, money, 0);
35+
return result;
36+
}
37+
private:
38+
int result = INT_MAX;
39+
};
40+
41+
class coinChange_dp {
42+
public:
43+
int solve(const int coins[], int n, int money){
44+
//这个找零问题,每次决策后有几个状态变量,第一个是当前的money,第二个是当前使用的硬币数量.所以状态里面至少要包含这两个变量
45+
46+
int max_coin_count = money; //n个1元
47+
bool st[max_coin_count][money+1];
48+
memset(st, false, sizeof(st));
49+
50+
//选择第一个硬币的初始状态
51+
for (int i=0; i<n; i++) {
52+
if (coins[i] <= money) {
53+
st[0][coins[i]] = true;
54+
}
55+
}
56+
57+
for (int index=1; index <= max_coin_count; index++) { //使用第index个硬币的状态
58+
for (int last_money = 1; last_money <= money; last_money++) {//计算出使用index个硬币所有可达的状态
59+
if (st[index-1][last_money]) { //如果last_money是可达状态,即可以通过硬币筹出来,那么计算下一个阶段的状态
60+
for (int k=n-1; k>=0; k--) {
61+
if (last_money + coins[k] <= money) {
62+
st[index][last_money + coins[k]] = true;
63+
}
64+
}
65+
}
66+
67+
if (st[index][money]) {
68+
return index+1;
69+
}
70+
}
71+
}
72+
return -1;
73+
74+
};
75+
};
76+
77+
78+
79+
80+
81+
void test_coinChange(){
82+
std::cout << "------------硬币找零问题----------\n" << std::endl;
83+
class coinChange so;
84+
class coinChange_dp so_dp;
85+
int coins[] = {1,3,5};
86+
std::cout << so.solve(coins, 3, 9) << std::endl;
87+
std::cout << so_dp.solve(coins, 3, 9) << std::endl;
88+
}
89+
90+
91+
#endif /* coinChange_hpp */

0 commit comments

Comments
 (0)