1- # 动态规? DP)
1+ # 动态规划( DP)
22
3- 动态规划是面试中最常被问道的题?但是一般情况下的都是常见的一些题?
3+ 动态规划是面试中最常被问道的题目,但是一般情况下的都是常见的一些题目.
441 . [ 百度百科] ( https://baike.baidu.com/item/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92/529408?fr=aladdin )
552 . [ 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```
1919int 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```
244244int dp[100000];
@@ -248,8 +248,8 @@ int MIN(int x,int y,int z){
248248}
249249int 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```
324324int a[101][101],s[101],ma[101];
@@ -335,13 +335,13 @@ int maxSum(int s[],int ma[],int m){//最大子序列的和
335335 return sum;
336336}
337337int 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```
466466int 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+ # 参考
5065061 . https://www.lintcode.com/problem/?tag=dynamic-programming
5075072 . https://www.geeksforgeeks.org/dynamic-programming/
0 commit comments