1、动态规划算法步骤(Dynamic Programming)
2、leetcode上适合用DP求解的问题
题目 | OJ地址 | 目录 |
Triangle | https://oj.leetcode.com/problems/triangle/ | 3.1 |
Maximum Subarray | https://oj.leetcode.com/problems/maximum-subarray/ | 3.2 |
Palindrome Partitioning II | https://oj.leetcode.com/problems/palindrome-partitioning-ii/ | 3.3 |
Minimum Path Sum | https://oj.leetcode.com/problems/minimum-path-sum/ | 3.4 |
Maximal Rectangle | https://oj.leetcode.com/problems/maximal-rectangle/ | 3.5 |
Interleaving String | https://oj.leetcode.com/problems/interleaving-string/ | 3.6 |
Edit Distance | https://oj.leetcode.com/problems/edit-distance/ | 3.7 |
Decode Ways | https://oj.leetcode.com/problems/decode-ways/ | 3.8 |
Best Time to Buy and Sell StocI&II&III | https://oj.leetcode.com/problems/best-time-to-buy-and-sell-stock/ | 3.9 |
Scramble String | https://oj.leetcode.com/problems/scramble-string/ | 3.10 |
Distinct Subsequences | https://oj.leetcode.com/problems/distinct-subsequences/ | 3.11 |
Word Break I&II | https://oj.leetcode.com/problems/word-break/ | 3.12 |
Unique Paths I & II | https://oj.leetcode.com/problems/unique-paths/ | 3.4 |
3、leetcode相关题目
3.1 Triangle
3.1.1 题目
Given a triangle, find the minimum path sum from top to bottom. Each step you may move to adjacent numbers on the row below.
For example, given the following triangle
1
2
3
4
5
6[ [2], [3,4], [6,5,7], [4,1,8,3] ]
The minimum path sum from top to bottom is 11
(i.e., 2 + 3 + 5 + 1 = 11).
Note:
O(n) extra space, where n is the total number of rows in the triangle.
3.1.2 分析
3.1.3 参考代码
1
2
3
4
5
6
7
8
9
10<span style="font-size:18px;">int minimumTotal(vector<vector<int> > &triangle) { int row=triangle.size(); //行,第row行的元素有row个 vector<vector<int> > f(triangle); //用f[m][n]记录从triangle[m][n]出发到叶子节点的最短路径和。也可以直接用triangle代替f,但会改变triangle for(int x=row-2;x>=0;x--) for(int y=0;y<=x;y++) f[x][y]=min(f[x+1][y],f[x+1][y+1])+triangle[x][y]; return f[0][0]; }</span>
(自底向上法的程序是迭代形式的)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24<span style="font-size:18px;">class Solution { public: int minimumTotal(vector<vector<int> > &triangle) { int row=triangle.size(); //行 vector<vector<int> > f(triangle); //f[m][n]表示从triangle[m][n]出发到叶子节点的最短路径和 for(int m=0;m<row-1;m++) for(int n=0;n<=m;n++) f[m][n]=INT_MAX; //与自底向上的方法不同,备忘录法必须将其初始化为标识值,以便“查找备忘录” f[row-1]=triangle[row-1]; //最后一行保持原值 return dp(0,0,triangle,f); //从根出发 } private: int dp(int x,int y,vector<vector<int> > &triangle,vector<vector<int> > &f){ if(f[x][y]!=INT_MAX) return f[x][y]; //查找备忘录,如果已经计算过,直接返回,避免重复计算 f[x][y]=min(dp(x+1,y,triangle,f),dp(x+1,y+1,triangle,f))+triangle[x][y]; return f[x][y]; } };</span>
(备忘录法的代码是递归形式的,但不同于递归程序的是,它有备忘录f[m][n],不会重复计算相同子问题)
3.2 Maximum Subarray
3.2.1 题目
Find the contiguous subarray within an array (containing at least one number) which has the largest sum.
For example, given the array [−2,1,−3,4,−1,2,1,−5,4]
,
[4,−1,2,1] has the largest sum = 6
.
3.2.2 分析
3.2.3 代码
1
2
3
4
5
6
7
8
9<span style="font-size:18px;">int maxSubArray(int A[], int n) { int sum=INT_MIN,b=0; for(int i=0;i<n;i++) { b=max(A[i],b+A[i]); sum=max(sum,b); } return sum; }</span>
3.3 Palindrome Partitioning II
3.3.1 题目
Given a string s, partition s such that every substring of the partition is a palindrome.
Return the minimum cuts needed for a palindrome partitioning of s.
For example, given s = "aab"
,
1 since the palindrome partitioning ["aa","b"]
could be produced using 1 cut.
3.3.2 分析
(2)计算f[2],即“cdddd”的最小切割数
(3)计算f[1],即"bcdddd”的最小切割数
(4)计算f[0],即"abcdddd”的最小切割数
3.3.3 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21<span style="font-size:18px;">int minCut(string s) { int n=s.size(); int f[n+1]; //f[i]表示字符串s[i...n-1]的最小切割数 for(int i=0;i<=n;i++) f[i]=n-i-1; //初始化为最坏情况,即每一处都切割。注意f[n]=-1是故意多出来的一个 bool p[n][n]; memset(p,false,n*n); /*确定p[i][j]*/ for(int i=n-1;i>=0;i--) for(int j=i;j<n;j++){ p[i][j]= s[i]==s[j] && (j-i<2 || p[i+1][j-1]); }//当s[i]==s[j]并且s[i+1..j-1]为回文串时,s[i..j]才为回文串。当s[i..j]长度小于3则只需判断s[i]==s[j] /*计算f[]*/ for(int i=n-1;i>=0;i--) for(int j=i;j<n;j++){ if(p[i][j]) f[i]=min(f[i],1+f[j+1]); } //这段代码其实可以直接将if语句写到上面的for for循环里,这里只是为了思想清晰 return f[0]; }</span>
3.4 Unique Paths、Unique Paths II、Minimum Path Sum
3.4.1 Unique Paths
3.4.1.1 题目
A robot is located at the top-left corner of a m x n grid (marked 'Start' in the diagram below).
The robot can only move either down or right at any point in time. The robot is trying to reach the bottom-right corner of the grid (marked 'Finish' in the diagram below).
How many possible unique paths are there?
Above is a 3 x 7 grid. How many possible unique paths are there?
Note: m and n will be at most 100.
3.4.1.2 分析
1
2
3
4
5int uniquePaths(int m, int n) { if(m<1 || n<1) return 0; if(m==1 && n==1) return 1; return uniquePaths(m-1,n)+uniquePaths(m,n-1); }
3.4.1.3 代码
1
2
3
4
5
6
7
8
9
10
11int uniquePaths(int m, int n) { if(m<1 || n<1) return 0; if(m==1 && n==1) return 1; int p[m+1][n+1];//p[i][j]表示:一个iXj的grid的path个数。p[m][n]即为所求 for(int i=1;i<=m;i++) for(int j=1;j<=n;j++){ if(i==1 || j==1) p[i][j]=1; //对于只有一行或者一列的网格,路径数肯定为1 else p[i][j]=p[i-1][j]+p[i][j-1]; } return p[m][n]; }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18class Solution { public: int uniquePaths(int m, int n) { this->p=vector<vector<int>> (m+1,vector<int>(n+1,0)); return dfs(m,n); } private: vector<vector<int>> p; int dfs(int m,int n){ if(m<1 || n<1) return 0; if(m==1 && n==1) return 1; return getp(m-1,n)+getp(m,n-1); } int getp(int m,int n ){ if(p[m][n]!=0) return p[m][n]; else p[m][n]=dfs(m,n); } };
3.4.2 Unique Paths II
3.4.2.1 题目
Follow up for "Unique Paths":
Now consider if some obstacles are added to the grids. How many unique paths would there be?
An obstacle and empty space is marked as 1
and 0
respectively in the grid.
For example,
There is one obstacle in the middle of a 3x3 grid as illustrated below.
1
2
3
4
5[ [0,0,0], [0,1,0], [0,0,0] ]
The total number of unique paths is 2
.
Note: m and n will be at most 100.
3.4.2.2 分析
3.4.2.3 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27int uniquePathsWithObstacles(vector<vector<int> > &obstacleGrid) { if(obstacleGrid.empty()) return 0; int m=obstacleGrid.size(); int n=obstacleGrid[0].size(); int p[m+1][n+1];//p[i][j]表示:iXj的grid的path个数(该grid是从obstacleGrid中以“终点”为右下顶点截取下来的) for(int i=1;i<=m;i++) for(int j=1;j<=n;j++){ if(obstacleGrid[m-i][n-j]==1) p[i][j]=0; //有障碍,p[i][j]=0 else if(i==1 && j==1){ //p[1][1]单独处理 p[i][j]=1; } else if(i==1){ p[1][j]=p[1][j-1]; //只能向右,取决于p[1][j-1] } else if(j==1){ p[i][1]=p[i-1][1]; //只能向下,取决于p[i-1][1] } else p[i][j]=p[i-1][j]+p[i][j-1]; //能向下或向右 } return p[m][n]; }
3.4.3 Minimum Path Sum
3.4.3.1 题目
Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right which minimizes the sum of all numbers along its path.
Note: You can only move either down or right at any point in time.
3.4.3.2 分析
3.4.3.3 代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23int minPathSum(vector<vector<int> > &grid) { if(grid.empty()) return 0; int m=grid.size(); int n=grid[0].size(); int p[m+1][n+1]; //p[i][j]表示iXj的grid的最小PathSum(该grid是从grid中以“终点”为右下顶点截取下来的),p[m][n]即为所求 /*自底向上法*/ for(int i=1;i<=m;i++) for(int j=1;j<=n;j++){ if(i==1 && j==1) p[1][1]=grid[m-1][n-1]; //p[1][1]单独处理 else if(i==1) p[i][j]=grid[m-i][n-j]+p[i][j-1]; //i=1,只能向右走 else if(j==1) p[i][j]=grid[m-i][n-j]+p[i-1][j]; //j=1,只能向下走 else p[i][j]=grid[m-i][n-j]+min(p[i-1][j],p[i][j-1]); //能向下或向右 } return p[m][n]; }
最后
以上就是甜甜棉花糖最近收集整理的关于【Leetcode】动态规划问题详解(持续更新)1、动态规划算法步骤(Dynamic Programming)2、leetcode上适合用DP求解的问题3、leetcode相关题目的全部内容,更多相关【Leetcode】动态规划问题详解(持续更新)1、动态规划算法步骤(Dynamic内容请搜索靠谱客的其他文章。
发表评论 取消回复