概述
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
[ [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 参考代码
<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>
(自底向上法的程序是迭代形式的)
<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 代码
<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 代码
<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 分析
int 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);
}
很明显,分治法对于重叠的子问题进行了重复计算,比如startbelow向右、startright向下会到达同一个格子g,上面的递归程序会计算两次uniquePaths(g)。
3.4.1.3 代码
int 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];
}
class 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.
[ [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 代码
int 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 代码
int 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 Programming)2、leetcode上适合用DP求解的问题3、leetcode相关题目所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复