动态规划1

1.62. 不同路径

思路:看到向右向下就可以用动态规划的方法,考虑边界,再找到递推公式。优化的话,可以将二维数组转化为一位数组。

public int uniquePaths(int m, int n) { 
     int[][] dp = new int[m][n]; 
    //第一列都是1 
    for (int i = 0; i < m; i++) { 
        dp[i][0] = 1; 
    } 
    //第一行都是1 
    for (int i = 0; i < n; i++) { 
         dp[0][i] = 1; 
    } 
 
    //这里是递推公式 
    for (int i = 1; i < m; i++) 
        for (int j = 1; j < n; j++) 
            dp[i][j] = dp[i - 1][j] + dp[i][j - 1]; 
    return dp[m - 1][n - 1]; 
 } 
class Solution {
    public int uniquePaths(int m, int n) {
        int[] dp = new int[m];
        Arrays.fill(dp,1);
        for(int j=1;j<n;j++)
            for(int i=1;i<m;i++)
                dp[i] = dp[i]+dp[i-1];
        return dp[m-1];
    }
}
2.剑指 Offer 47. 礼物的最大价值

动态规划:

①边界考虑

  • 如果在i=0,j=0处,dp[i][j]=grid[i][j]
  • 如果在最上面,则为第一行元素,那就只能让行元素累加
  • 如果在最左边,那就上列元素累加
  • 如果都不在,那就让礼物价值的点加上二者的最大值

②转移方程

dp[i][j]=max(dp[i-1][j],dp[i][j-1])+grid[i][j]; 
class Solution {
    public int maxValue(int[][] grid) {
        if(grid==null || grid.length==0)
            return 0;
        int m = grid.length;
        int n = grid[0].length;
        int[][] dp = new int[m][n];
        dp[0][0] = grid[0][0];
        for(int i=1;i<n;i++){
            dp[0][i] = grid[0][i] + dp[0][i-1]; 
        }
        for(int i=1;i<m;i++){
            dp[i][0] = grid[i][0] + dp[i-1][0]; 
        }
        for(int i=1;i<m;i++)
            for(int j=1;j<n;j++)
                dp[i][j] = Math.max(dp[i-1][j],dp[i][j-1]) + grid[i][j];
        return dp[m-1][n-1];

    }
}
//边界判断
if(grid==null||grid.length==0)
    return 0;
int m=grid.length;
int n=grid[0].length;
//初始化dp的最上面一行,从左到右累加
for(int i=1;i<n;i++){
    grid[0][i] = grid[0][i]+grid[0][i-1];
}
//初始化dp的最左边一列,从上到下累加
for(int i=1;i<m;i++){
    grid[i][0] = grid[i][0]+grid[i-1][0];
}
//递推公式
for(int i=1;i<m;i++){
    for(int j=1;j<n;j++){
        grid[i][j] = grid[i][j] + Math.max(grid[i][j-1],gridi-1][j]);
    }    
}
return grid[m-1][n-1];

3.647. 回文子串

动态规划:

//字符串的长度
int length=s.length();
boolean[] dp = new boolean[length];
int count = 0;
for(int j=0;j<length;j++){
    for(int i=0;i<=j;i++){
        if(s.charAt(i) == s.charAt(j) && (j-i<=2 || dp[i+1])){
            dp[i]=true;
            count ++;
        }else{
            dp[i] = false;
        }
    }    
}
return count;

中心扩散法:

int length = s.length();
int size = 2 * length-1;
int count = 0;
for(int i=0;i<size;i++){
    int left = i/2;
    int right = left + i%2;
    while(left>=0&&right<length&&s.charAt(left)==s.charAt(right)){
        left--;
        right++;
        count++;
    }
}
return count;
4.1277. 统计全为 1 的正方形子矩阵
class Solution {
    public int countSquares(int[][] matrix) {
        int m = matrix.length;
        int n = matrix[0].length;
        int[][] dp = new int[m][n];
        int ans = 0;
        // 预处理每一行和每一列
        for (int i = 0; i < m; i++) {
            ans += dp[i][0] = matrix[i][0];
        }
        for (int j = 0; j < n; j++) {
            ans += dp[0][j] = matrix[0][j];
        }
        // 上述过程(0, 0)判断了两次, 如果matrix[0][0] == 1,说明ans多算了一个
        if (matrix[0][0] == 1) {
            ans--;
        }
        for (int i = 1; i < m; i++) {
            for (int j = 1; j < n; j++) {
                if (matrix[i][j] == 1) {
                    dp[i][j] = Math.min(Math.min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
                    ans += dp[i][j];
                }
            }
        }
        return ans;
    }
}
54.221. 最大正方形
class Solution {
    public int maximalSquare(char[][] matrix) {
        int m = matrix.length;
        int n = matrix[0].length;
        int[][] dp = new int[m+1][n+1];
        int maxside = 0;
        for(int i=1;i<=m;i++){
            for(int j=1;j<=n;j++){
                if(matrix[i-1][j-1]=='1'){
                    dp[i][j] = Math.min(dp[i-1][j],Math.min(dp[i-1][j-1],dp[i][j-1]))+1;
                    maxside = Math.max(maxside,dp[i][j]);
                }
            }
        }
        return maxside * maxside;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值