力扣150题——多维动态规划
交错字符串
题目
97. 交错字符串 - 力扣(LeetCode)
思路
用dp[i][j]代表s1的前i个字母和s2的前s2个字母能否交错组成s3的前i+j-1的子串
状态转移方程即为
- 如果 s1[i-1] == s3[i + j - 1],并且 dp[i-1][j] 为 true,则 dp[i][j] 也为 true。
- 如果 s2[j-1] == s3[i + j - 1],并且 dp[i][j-1] 为 true,则 dp[i][j] 也为 true。
代码
public boolean isInterleave(String s1, String s2, String s3) {
int n=s1.length(),m=s2.length(),l=s3.length();
if(n+m!=l){
return false;
}
boolean[][] dp = new boolean[n+1][m+1];
dp[0][0] = true;
for(int i=1;i<=n;i++){
dp[i][0]=dp[i-1][0]&&s1.charAt(i-1)==s3.charAt(i-1);
}
for(int i=1;i<=m;i++){
dp[0][i]=dp[0][i-1]&&s2.charAt(i-1)==s3.charAt(i-1);
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(dp[i-1][j]&&s1.charAt(i-1)==s3.charAt(i+j-1)){
dp[i][j]=true;
}else if(dp[i][j-1]&&s2.charAt(j-1)==s3.charAt(i+j-1)){
dp[i][j]=true;
}
}
}
return dp[n][m];
}
买卖股票的最佳时机Ⅲ
题目
123. 买卖股票的最佳时机 III - 力扣(LeetCode)
思路
- 设 dp[i][j][0] 表示第 i 天,最多进行 j 次交易,并且当前不持有股票的最大利润。
- 设 dp[i][j][1] 表示第 i 天,最多进行 j 次交易,并且当前持有股票的最大利润。
状态转移方程:
- dp[i][k][0] = max(dp[i-1][j][0], dp[i-1][j][1] + prices[i])
- 即今天不持有股票有两种情况:
- 昨天也不持有股票,或者
- 昨天持有股票,今天卖出股票。
- dp[i][k][1] = max(dp[i-1][j][1], dp[i-1][j-1][0] - prices[i])
- 即今天持有股票也有两种情况:
- 昨天也持有股票,或者
- 昨天不持有股票,今天买入股票。
代码
public int maxProfit(int[] prices) {
int n = prices.length;
if(n==0){
return 0;
}
int[][][] dp = new int[n][3][2];
for(int i=0;i<3;i++){
dp[0][i][0]=0;
dp[0][i][1]=-prices[0];
}
for(int i=1;i<n;i++){
for(int j=1;j<3;j++){
dp[i][j][0]=Math.max(dp[i-1][j][0],dp[i-1][j][1]+prices[i]);
dp[i][j][1]=Math.max(dp[i-1][j][1],dp[i-1][j-1][0]-prices[i]);
}
}
return dp[n-1][2][0];
}
买卖股票的最佳时机Ⅳ
题目
188. 买卖股票的最佳时机 IV - 力扣(LeetCode)
思路
只需要在上一题的基础上讲k的值化为动态的,并且最后遍历所有的K,找出能达到最大利益的K,并返回最大值。
代码
public int maxProfit(int k, int[] prices) {
int n = prices.length;
if(n==0||k==0){
return 0;
}
int[][][] dp = new int[n][k+1][2];
for(int i=0;i<=k;i++){
dp[0][i][0]=0;
dp[0][i][1]=-prices[0];
}
for(int i=1;i<n;i++){
for(int j=1;j<=k;j++){
dp[i][j][0]=Math.max(dp[i-1][j][0],dp[i-1][j][1]+prices[i]);
dp[i][j][1]=Math.max(dp[i-1][j][1],dp[i-1][j-1][0]-prices[i]);
}
}
int max = Integer.MIN_VALUE;
for(int i=0;i<=k;i++){
max = Math.max(dp[n-1][i][0],max);
}
return max;
}
最大正方形
题目
221. 最大正方形 - 力扣(LeetCode)
思路
dp[i][j]
表示以位置(i, j)
作为正方形右下角的最大正方形的边长。- 若 matrix[i][j] == '1',则 dp[i][j] 的值由 dp[i-1][j](上)、dp[i][j-1](左)和 dp[i-1][j-1](左上)的最小值加1决定。
代码
public int maximalSquare(char[][] matrix) {
int n = matrix.length;
if(n==0){
return 0;
}
int m = matrix[0].length;
int[][] dp = new int[n][m];
int max = Integer.MIN_VALUE;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
if(matrix[i][j]=='1'){
if(i==0||j==0){
dp[i][j]=1;
}else{
dp[i][j]=Math.min(dp[i-1][j],Math.min(dp[i-1][j-1],dp[i][j-1]))+1;
}
max = Math.max(max,dp[i][j]);
}
}
}
return max*max;
}