Skip to content

Commit b56ff40

Browse files
committed
Fix: resolve formatting issues and typos
1 parent a917f4b commit b56ff40

14 files changed

Lines changed: 862 additions & 677 deletions

File tree

docs/01-algorithm-basics/algorithm-concepts/dynamic-programming.md

Lines changed: 50 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
# 动态规?DP)
1+
# 动态规划(DP)
22

3-
动态规划是面试中最常被问道的题?但是一般情况下的都是常见的一些题?
3+
动态规划是面试中最常被问道的题目,但是一般情况下的都是常见的一些题目.
44
1. [百度百科](https://baike.baidu.com/item/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/529408?fr=aladdin)
55
2. [wikipedia](https://en.wikipedia.org/wiki/Dynamic_programming)
66

77

88
## 1. 最长上升子序列
9-
> **题目**: 最长上升子序列问题是在一个无序的给定序列中找到一个尽可能长的由低到高排列的子序列,这种子序列不一定是连续的或者唯一?
9+
> **题目**: 最长上升子序列问题是在一个无序的给定序列中找到一个尽可能长的由低到高排列的子序列,这种子序列不一定是连续的或者唯一的.
1010
1111
> **解析**:
1212
13-
dp[j]: 表示以j结尾的最长子序列的长?
13+
dp[j]: 表示以j结尾的最长子序列的长度,
1414
dp[j] = max(dp[j], dp[i]+1) if(a[i]<d[j]) {i in [1,j]}
1515

1616
return max(dp[1-n])
17-
使用二分查找可以得到O(nlog)的算?这里就不给出,思路也很简?读者自行查?
17+
使用二分查找可以得到O(nlog)的算法,这里就不给出,思路也很简单,读者自行查询.
1818
```
1919
int lis(vector<int> &nums) {
2020
if(nums.size() == 0) return 0;
@@ -34,7 +34,7 @@ int lis(vector<int> &nums) {
3434
}
3535
```
3636
## 2. 最长公共子序列
37-
> **题目**: 给出两个字符串,找到最长公共子序列(LCS),返回LCS的长度?
37+
> **题目**: 给出两个字符串,找到最长公共子序列(LCS),返回LCS的长度
3838
3939
> **解析**:
4040
@@ -55,8 +55,8 @@ int lcs(string &A, string &B) {
5555
return dp[A.size()][B.size()];
5656
}
5757
```
58-
## 3. 最长整除子?
59-
> **题目**: 给定一个n个正整数的数? 找出最长的子序?使得序列中每一个较小的数都能整除较大的?
58+
## 3. 最长整除子集
59+
> **题目**: 给定一个n个正整数的数组, 找出最长的子序列,使得序列中每一个较小的数都能整除较大的数.
6060
6161
> Example:
6262
@@ -66,7 +66,7 @@ int lcs(string &A, string &B) {
6666
因为: 20能被整除10, 10能被5整除.
6767
> **解析**: 这个可以参考最长上升子序列, 首先排序数组.
6868
>
69-
dp[i]: 表示下标i结尾?最长的子序列长?
69+
dp[i]: 表示下标i结尾的,最长的子序列长度
7070
if(a[j] % a[i] == 0) dp[j] = max(dp[j], dp[i]+1) j in [i+1, n]
7171

7272

@@ -110,12 +110,12 @@ int backPack(int m, vector<int> A) {
110110
}
111111
```
112112
## 5. 编辑距离
113-
> **题目**: 给出两个单词word1和word2,计算出将word1 转换为word2的最少操作次数?
114-
你总共三种操作方法?
113+
> **题目**: 给出两个单词word1和word2,计算出将word1 转换为word2的最少操作次数
114+
你总共三种操作方法
115115

116-
插入一个字?
117-
删除一个字?
118-
替换一个字?
116+
插入一个字符
117+
删除一个字符
118+
替换一个字符
119119

120120

121121
> **解析**:
@@ -144,20 +144,20 @@ int minDistance(string &word1, string &word2) {
144144
}
145145
```
146146
## 6. 矩阵链乘
147-
> **题目**: 给你一个矩阵序? 找到有效的方式把这些数相乘到一?
147+
> **题目**: 给你一个矩阵序列, 找到有效的方式把这些数相乘到一起.
148148
> Example:
149149
150150
Input: p[] = {40, 20, 30, 10, 30}
151151
Output: 26000
152152

153153
表示四个矩阵,分别是A:40x20, B:20x30, C;30x10, D:10x30.
154-
最优的方式? (A(BC))D -->
154+
最优的方式是: (A(BC))D -->
155155
20*30*10 + 40*20*10 + 40*10*30
156156

157157

158158
> **解析**:
159159
160-
dp[i][j]: 表示[i,j]区间上最小?
160+
dp[i][j]: 表示[i,j]区间上最小值.
161161
dp[i][j] = min(dp[i][j], dp[i][k]+dp[k+1][j]+p[i-1]*p[k]*p[l]) k in [i,j-1]
162162

163163
```
@@ -182,27 +182,27 @@ int MatrixChainOrder(int p[], int n) {
182182
}
183183
```
184184
## 7. 回文划分
185-
> **题目**:给定字符?s, 需要将它分割成一些子? 使得每个子串都是回文?
186-
最少需要分割几?
185+
> **题目**:给定字符串 s, 需要将它分割成一些子串, 使得每个子串都是回文串.
186+
最少需要分割几次?
187187

188188
> **Example**:
189189
190190
样例 1:
191191
输入: "a"
192192
输出: 0
193-
解释: "a" 本身就是回文? 无需分割
193+
解释: "a" 本身就是回文串, 无需分割
194194

195195
样例 2:
196196
输入: "aab"
197197
输出: 1
198-
解释: ?"aab" 分割一? 得到 "aa" ?"b", 它们都是回文?
198+
解释: "aab" 分割一次, 得到 "aa" "b", 它们都是回文串.
199199

200200

201201
> **解析**:
202202
203-
可以看作序列型动态规划问? 设定 dp[i] 表示原串的前 i 个字符最少分割多少次可以使得到的都是回文子串.
203+
可以看作序列型动态规划问题, 设定 dp[i] 表示原串的前 i 个字符最少分割多少次可以使得到的都是回文子串.
204204

205-
如果 s ?i 个字符组成的子串本身就是回文? ?dp[i] = 0, 否则:
205+
如果 s 前 i 个字符组成的子串本身就是回文串, 则 dp[i] = 0, 否则:
206206

207207
dp[i] = min{dp[j] + 1} (j < i 并且 s[j + 1], s[j + 2], ... , s[i] 是回文串)
208208

@@ -236,9 +236,9 @@ int minCut(string s) {
236236
```
237237

238238
## 8. 丑数
239-
> **题目**:设计一个算法,找出只含素因??? 的第 n 小的数?
239+
> **题目**:设计一个算法,找出只含素因子2,3,5 的第 n 小的数
240240
241-
> **解析**: 使用2,3,5进行组合,得到第n个丑?
241+
> **解析**: 使用2,3,5进行组合,得到第n个丑数.
242242
243243
```
244244
int dp[100000];
@@ -248,8 +248,8 @@ int MIN(int x,int y,int z){
248248
}
249249
int nthUglyNumber(int n) {
250250
dp[1] = 1;
251-
int i2,i3,i5; // 分别表示2,3,5的对应的数,目标是使用前面的数字构造后面的数字?
252-
// 不能使用2,3,5的倍数进行构造,否则会出现错?
251+
int i2,i3,i5; // 分别表示2,3,5的对应的数,目标是使用前面的数字构造后面的数字
252+
// 不能使用2,3,5的倍数进行构造,否则会出现错误
253253
i2 = i3 = i5 = 1;
254254
int i=2;
255255
while(i<=n){
@@ -265,12 +265,12 @@ int nthUglyNumber(int n) {
265265
return dp[n];
266266
}
267267
```
268-
## 9. 最小花费路?
269-
> **题目**: 给定一个矩?求出从左上角到右下角的最小路径的?
268+
## 9. 最小花费路径
269+
> **题目**: 给定一个矩阵,求出从左上角到右下角的最小路径的和.
270270
271271
> **解析**:
272272
273-
dp[i][j]: (0,0)?i,j)的最小路径的?
273+
dp[i][j]: (0,0)到(i,j)的最小路径的和.
274274
dp[i][j] = min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1])+a[i][j]
275275

276276
```
@@ -303,11 +303,11 @@ int min(int x, int y, int z) {
303303
}
304304
```
305305
## 10. 最大矩阵和
306-
> **题目**: 给定一个由整数组成二维矩阵(r*c),现在需要找出它的一个子矩阵,使得这个子矩阵内的所有元素之和最大,并把这个子矩阵称为最大子矩阵?
306+
> **题目**: 给定一个由整数组成二维矩阵(r*c),现在需要找出它的一个子矩阵,使得这个子矩阵内的所有元素之和最大,并把这个子矩阵称为最大子矩阵
307307
308308
> Example:
309309
310-
例子?
310+
例子
311311
0 -2 -7 0
312312
9 2 -6 2
313313
-4 1 -4 1
@@ -316,9 +316,9 @@ int min(int x, int y, int z) {
316316
9 2
317317
-4 1
318318
-1 8
319-
其元素总和?5?
319+
其元素总和为15。
320320

321-
> **解析**: 将矩阵进行求和压缩到一维形?之后使用一维数组的最大子段和进行计算.
321+
> **解析**: 将矩阵进行求和压缩到一维形式,之后使用一维数组的最大子段和进行计算.
322322
323323
```
324324
int a[101][101],s[101],ma[101];
@@ -335,13 +335,13 @@ int maxSum(int s[],int ma[],int m){//最大子序列的和
335335
    return sum;
336336
}
337337
int maxMatrixSum(int n, int m) {
338-
int res=INT_MIN;//注意序列的最小?
338+
int res=INT_MIN;//注意序列的最小值
339339
    for(int i=0;i<n;i++){
340340
        memset(s,0,sizeof(s));
341341
        for(int j=i;j<n;j++){
342342
            int sum=0;
343343
            for(int k=0;k<m;k++){
344-
                s[k]+=a[j][k];//转化为一维数?
344+
                s[k]+=a[j][k];//转化为一维数组
345345
            }
346346
            sum=maxSum(s,ma,m);
347347
            if(sum>res) res=sum;
@@ -351,7 +351,7 @@ int maxMatrixSum(int n, int m) {
351351
}
352352
```
353353
## 11. 最大正方形面积
354-
> **题目**: 给你一个二维矩阵,权值为False和True,找到一个最大的正方形,使得里面的值全部为True,输出它的面?
354+
> **题目**: 给你一个二维矩阵,权值为False和True,找到一个最大的正方形,使得里面的值全部为True,输出它的面积.
355355
356356
> Example:
357357
@@ -367,7 +367,7 @@ int maxMatrixSum(int n, int m) {
367367

368368
> **解析**:
369369
370-
构造辅助数?dp[m][n],
370+
构造辅助数组,dp[m][n],
371371

372372
用m[i][j]表示右下角的1.
373373
if m[i][j]=1 then
@@ -401,9 +401,9 @@ int MaxSubSquare(vector<vector<bool>> &matrix) {
401401
}
402402
```
403403
## 12. 二进制串个数
404-
> **题目**: 求长度为n?1组成的二进制串中,没有连续1的串的个?
404+
> **题目**: 求长度为n的01组成的二进制串中,没有连续1的串的个数.
405405
406-
> **解析**: 分别用a[i]和b[i],表示长度为i,分别0结尾?结尾的串的个? 那么
406+
> **解析**: 分别用a[i]和b[i],表示长度为i,分别0结尾和1结尾的串的个数. 那么
407407
408408
a[i+1] = a[i] + b[i] // 在后面加0
409409
b[i+1] = a[i] // 只能在结尾是0的后面加1
@@ -419,11 +419,11 @@ int countStrings(int n) {
419419
return a[n-1] + b[n-1];
420420
}
421421
```
422-
## 13. 交叉字符?
423-
> **题目**: 给出三个字符?s1、s2、s3,判断s3是否由s1和s2交叉构成?
422+
## 13. 交叉字符串
423+
> **题目**: 给出三个字符串:s1、s2、s3,判断s3是否由s1和s2交叉构成
424424
> **解析**:
425425
426-
dp[i][j]: s1[1,i] ?s2[1,j] 是否能够组成s3[i+j]
426+
dp[i][j]: s1[1,i] s2[1,j] 是否能够组成s3[i+j]
427427

428428
dp[i][j] = dp[i][j] || dp[i-1][j] if s1[i] == s3[i+j-1]
429429

@@ -435,7 +435,7 @@ bool isInterleave(string &s1, string &s2, string &s3) {
435435
int dp[s1.size() + 1][s2.size() + 1] = {0};
436436
dp[0][0] = 1;
437437
int ok = 1;
438-
// 初始?
438+
// 初始化
439439
for(int i = 1; i <= s1.length(); i++) {
440440
dp[i][0] = dp[i - 1][0] && s1[i - 1] == s3[i - 1];
441441
}
@@ -459,15 +459,15 @@ bool isInterleave(string &s1, string &s2, string &s3) {
459459
```
460460

461461
## 14. 乘积最大子序列
462-
> **题目**: 找出一个序列中乘积最大的连续子序列(至少包含一个数)?
463-
> **解析**: 这里可以借鉴和最大的子序?但是需要每次保存两个?一个最大值和最小?(因为存在负负得正).
462+
> **题目**: 找出一个序列中乘积最大的连续子序列(至少包含一个数)
463+
> **解析**: 这里可以借鉴和最大的子序列,但是需要每次保存两个值,一个最大值和最小值,(因为存在负负得正).
464464
465465
```
466466
int maxProduct(vector<int> &nums) {
467467
int premin, premax, ans;
468468
premin = premax = ans = nums[0];
469469
for(int i=1;i<nums.size();i++){
470-
// 每次更新最大最小?保证负负得正
470+
// 每次更新最大最小值,保证负负得正
471471
// 这里使用滚动变量表示dp
472472
int curmax = max(max(premax*nums[i],premin*nums[i]),nums[i]);
473473
int curmin = min(min(premax*nums[i],premin*nums[i]),nums[i]);
@@ -481,8 +481,8 @@ int maxProduct(vector<int> &nums) {
481481
482482
```
483483
## 15. k个数之和
484-
> **题目**: 给定 n 个不同的正整数,整数 k(k <= n)以及一个目标数?target。在?n 个数里面找出 k 个数,使得这 k 个数的和等于目标数字,求问有多少种方案?
485-
> **解析**: dp[j][s]比碍事j个数组合s的个?
484+
> **题目**: 给定 n 个不同的正整数,整数 k(k <= n)以及一个目标数字 target。在这 n 个数里面找出 k 个数,使得这 k 个数的和等于目标数字,求问有多少种方案?
485+
> **解析**: dp[j][s]比碍事j个数组合s的个数,
486486
> dp[j][s] += dp[j-1][s-A[i]] {i: [0,n)}
487487
488488
```int kSum(vector<int> &A, int k, int target) {
@@ -502,6 +502,6 @@ int maxProduct(vector<int> &nums) {
502502
```
503503

504504

505-
# 参?
505+
# 参考
506506
1. https://www.lintcode.com/problem/?tag=dynamic-programming
507507
2. https://www.geeksforgeeks.org/dynamic-programming/

0 commit comments

Comments
 (0)