动态规划总结(1)

今日开始稍微学习动态规划,前来总结下每日战绩、

1.LeetCode 120,三角形最小路径和

例如,给定三角形:

[
    [2],
   [3,4],
  [6,5,7],
 [4,1,8,3]
]

自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。

首先,看到这道题可以想出,就是从上往下走,2可以到3也可以到4,后面同理,因此,很明显是一道动态规划问题。
开始想法是从上往下,比如站在5的位置,5可以从3,4转移而来,但是站在6的位置,可以从边界和3而来,那么边界设置一个INT_MAX,也可以递推过来.
但是看视频学习到大佬直接从下往上递推,站在5的角度,可以从1,8转换过来,那么就不用处理边界问题了。

class Solution {
    public int minimumTotal(List<List<Integer>> triangle) {
        int row = triangle.size();
        int [] f= new int [row+1];
        for(int i=row-1;i>=0;i--){
            for(int j=0;j<=i;j++){
                f[j]=Math.min(f[j],f[j+1])+triangle.get(i).get(j);
            }
        }
        return f[0];
    }
}

2.LeetCode 63,不同路径 II

之前做过不同路径I ,也是一个动态规划,这道题多了一些障碍物,但是依然是一道典型的动态规划问题。
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。

输入:
[
[0,0,0],
[0,1,0],
[0,0,0]
]
输出:
2
解释: 3x3 网格的正中间有一个障碍物。
从左上角到右下角一共有 2 条不同的路径:

  1. 向右 -> 向右 -> 向下 -> 向下
  2. 向下 -> 向下 -> 向右 -> 向右
class Solution {
    int n,m;
    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        n=obstacleGrid.length;
        m=obstacleGrid[0].length;
        int [][] f = new int [n][m];
        if(obstacleGrid [0][0]==0)f[0][0]=1;
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++){
                if(obstacleGrid[i][j]!=1){
                    if(i!=0)f[i][j]+=f[i-1][j];
                    if(j!=0)f[i][j]+=f[i][j-1];
                }
            }
        return f[n-1][m-1];
    }
}

Leecode 338.比特位计数

给定一个非负整数 num。对于 0 ≤ i ≤ num 范围中的每个数字 i ,计算其二进制数中的 1 的数目并将它们作为数组返回。
示例 1:
输入: 2
输出: [0,1,1]

常规思路 分别遍历求每个数1的个数即可
但是题目要求采用O(n)的时间,
那么这么想,如果求5中1的个数,5的二进制表示是101
不看最后一位 前两位中1的个数也就是2中1的个数
因此状态转移方程为 f [ i ] = f [ i > > 1 ] + ( i & 1 ) f[i]=f[i>>1]+(i\&1) f[i]=f[i>>1]+(i&1)

class Solution {
    public int[] countBits(int num) {
        int [] f= new int [num+1];
        f[0]=0;
        for(int i=1;i<=num;i++){
            f[i]=f[i>>1]+(i&1);
        }
        return f;
    }
}

LeetCode 322.零钱兑换

给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。
输入: coins = [1, 2, 5], amount = 11
输出: 3
解释: 11 = 5 + 5 + 1

思考:他让求最少硬币个数,那么状态转移就是一直+1,最后判断最后的一个状态是否满足要求。
状态转移方程 f [ n ] = m i n ( f [ n ] , f [ n − j ] + 1 ) f[n]=min(f[n],f[n-j]+1) f[n]=min(f[n],f[nj]+1)
另外,除了第一个,其他都需要置一个很大的值,比总金额大即可

class Solution {
    public int coinChange(int[] coins, int amount) {
        int [] f= new int [amount+1];
        Arrays.fill(f,amount+1);
        f[0]=0;
        for(int i=0;i<coins.length;i++)
            for(int j=coins[i];j<=amount;j++)
                f[j]=Math.min(f[j],f[j-coins[i]]+1);
        return f[amount]!=amount+1?f[amount]:-1;
    }
}

LeetCode 329.矩阵中的最长递增路径

输入: nums =
[
[9,9,4],
[6,6,8],
[2,1,1]
]
输出: 4
解释: 最长递增路径为 [1, 2, 6, 9]。

这道题,其实主要考察的应该是深搜+记忆化搜索。
遍历每个元素,然后从每个元素为中心深搜,之后将参数保存起来,下次如果在缓冲区,直接拿来用。
代码如下

class Solution {
    private static int n,m;
    private static int [] dx={0,1,0,-1},dy={-1,0,1,0};
    private static int [][] dp ;
    public int dfs(int [][] matrix,int x,int y){
        if(dp[x][y]!=0)return dp[x][y];
        for(int i=0;i<4;i++){
            int a=x+dx[i],b=y+dy[i];
            if(a>=0 && a<n && b>=0 && b<m && matrix[x][y] < matrix[a][b])
                dp[x][y]=Math.max(dp[x][y],dfs(matrix,a,b)+1);
        }
        return dp[x][y];
    }
    public int longestIncreasingPath(int[][] matrix) {
        if(matrix.length==0 || matrix[0].length == 0)return 0;
        n=matrix.length;
        m=matrix[0].length;
        dp = new int [n][m];
        int res =0;
        for(int i=0;i<n;i++)
            for(int j=0;j<m;j++)
                res=Math.max(res,dfs(matrix,i,j));
        return ++res;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值