leetcode之动态规划刷题总结2

Posted nuist__NJUPT

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode之动态规划刷题总结2相关的知识,希望对你有一定的参考价值。

leetcode之动态规划刷题总结2

1-跳跃游戏
题目链接:题目链接戳这里!!!
思想:dp[i]表示在第i个位置能否跳到最后,从后向前遍历,如果前一个位置的数字大于等于1,代表可以跳到下一个位置,否则前一个位置跳不到当前位置,再往前一个位置想跳到当前位置就必须能跳跃的距离大于等于2,依次类推。

AC代码如下:

class Solution 
    public boolean canJump(int[] nums) 
        int lens = nums.length ;
        boolean [] dp = new boolean [lens] ;
        int cnt = 1 ;
        dp[lens-1]=true ;
        for(int i=lens-1; i>=1; i--)
            if(nums[i-1]>=cnt)
                dp[i-1] = true ;
                cnt = 1 ;
            else
                cnt ++ ;
            
        
        return dp[0] ;
    

2-跳跃游戏II
题目链接:题目链接戳这里!!!
思路:这题用动态规划的效率并不是太高,dp[i]表示从位置0跳到位置i所需的最小次数,初始化dp[0]为0,后面分别遍历从1到lens-1位置,所需的最小跳跃次数。
AC代码如下:

class Solution 
    public int jump(int[] nums) 
        int lens = nums.length ;
        int [] dp = new int [lens] ; 
        dp[0] = 0 ;
        for(int i=1; i<lens; i++)
            dp[i] = Integer.MAX_VALUE;
            for(int j=0; j<i; j++)
                if(nums[j]>=i-j)
                    dp[i] = Math.min(dp[i], dp[j] + 1) ;
                
            
        
        return dp[lens-1] ;
    


3-最小路径和
题目链接:题目链接戳这里!!!

这题用grid数组做为dp数组初始化第一行和第一列,因为只能往下和往右走,所以第一行和第一列的最短路径是固定的,dp[i][j]是到达(i,j)所需的最短路径,然后递推表达式:dp[i][j] = dp[i][j-1]+dp[i-1][j],即到达其余所有的最短路径取决于左边和上方的最小值。

AC代码如下:

class Solution 
    public int minPathSum(int[][] grid) 
        int m = grid.length ;
        int n = grid[0].length ;
        for(int i=1; i<n; i++)
            grid[0][i] += grid[0][i-1] ;
        
        for(int i=1; i<m; i++)
            grid[i][0] += grid[i-1][0] ;
        
        for(int i=1; i<m; i++)
            for(int j=1; j<n; j++)
                grid[i][j] += Math.min(grid[i][j-1], grid[i-1][j]) ;
            
        
        return grid[m-1][n-1] ;



4-不同路径
题目链接:题目链接戳这里!!!

思路:这题和上一题很像,dp[i][j]表示到达(i,j)有多少条路径,第一行和第一列的dp要初始化为1,因为所有点只有一种,其余的点的路径数量等于左边和上方点的路径总和。

AC代码如下:

class Solution 
    public int uniquePaths(int m, int n) 
        int [][] dp = new int [m][n] ;
        for(int i=0; i<m; i++)
            dp[i][0] = 1 ;
        
        for(int j=0; j<n; j++)
            dp[0][j] = 1 ;
        
        for(int i=1; i<m; i++)
            for(int j=1; j<n; j++)
                dp[i][j] += (dp[i][j-1] + dp[i-1][j]) ;
            
        
        return dp[m-1][n-1] ;
    


5-不同路径II
题目链接:题目链接戳这里!!!
思路:这题和上一题很像,不过难了一点,因为加了障碍物,dp[i][j]数组表示到达位置(i,j)有多少条路径,我们初始化第一行和第一列为1,一旦发现有障碍物,后面就不用初始化了,然后从第一行第一列开始每个位置等于左方和上方的可能路径之和,如果当前位置有障碍,直接跳过就可以。

class Solution 
    public int uniquePathsWithObstacles(int[][] obstacleGrid) 
        int m = obstacleGrid.length ;
        int n = obstacleGrid[0].length ;
        int [][] dp = new int [m][n] ;
        for(int j=0; j<n; j++)
            if(obstacleGrid[0][j]==1)
                break ;
            else
                dp[0][j] = 1 ;
            
        
        for(int i=0; i<m; i++)
            if(obstacleGrid[i][0] == 1)
                break ;
            else
                dp[i][0] = 1 ;
            
        
        for(int i=1; i<m; i++)
            for(int j=1; j<n; j++)
                if(obstacleGrid[i][j]==1)
                    continue ;
                else
                    dp[i][j] += dp[i][j-1] + dp[i-1][j] ;
                
            
        
        return dp[m-1][n-1] ;
    

6-三角形最小路径和
题目链接:题目链接戳这里!!!

思路:自底向上,把两个值中小的那个依次加到上层,依次迭代到最顶端就可以了。

AC代码如下:

class Solution 
    public int minimumTotal(List<List<Integer>> triangle) 
        int row = triangle.size() ;
        int col = triangle.size() ;
        int [][] dp = new int [row][col] ;
      
        for(int i=0; i<triangle.size(); i++)
            for(int j=0; j<triangle.get(i).size(); j++)
               dp[i][j] = triangle.get(i).get(j) ;
            
        

        for(int i=row-1; i>=0; i--)
            for(int j=0; j<=i; j++)
                if(i-1>=0 && j+1<=i)
             dp[i-1][j] += Math.min(dp[i][j],dp[i][j+1]) ;
            
        
       return dp[0][0] ;
    


7-买卖股票的最佳时机
题目链接:题目链接戳这里!!!

思路:这题不难,不过容易容易超时,不支持O(n^2)的时间复杂度,这题的思路是记录之前购买的最小值,并且计算当前卖出的最大值,一轮遍历的最大值就是卖股票盈利最多的。

AC代码如下:

class Solution 
    public int maxProfit(int[] prices) 
        int n = prices.length ;
        int min = prices[0] ;
        int max = 0 ;
        for(int i=1; i<n; i++)
             max = Math.max(max, prices[i]-min) ; //记录当前天卖出去的最大值
             min = Math.min(min, prices[i]) ;//记录之前所有天买入的最小值
        
        return max ;
      
    


8-买股票的最佳时机II
题目链接:题目链接戳这里!!!

这题比较好想的是贪心策略,只要当前天股票价格比前一天股票价格高,就将股票卖出,就是获利最大的。

AC代码如下:

class Solution 
    public int maxProfit(int[] prices) 
     int max = 0 ;
     for(int i=1; i<prices.length; i++)
         if(prices[i]>prices[i-1])
             max += (prices[i]-prices[i-1]) ;
         
     
     return max ;   
    


当然这题主要还是考的动态规划
思路:第i天就两种状态,持有股票或者不持有股票
若持有股票,则又分为两种情况:1-前一天就持有,2-今天买入
若不持有股票,也分为两种情况:1-前一天不持有,2-今天卖出
我们最后找到最后依次不持有,就是我们的答案了
dp[i][1]:表示第i天持有
dp[i][0]:表示第i天不持有

AC代码如下:

class Solution 

    public int maxProfit(int[] prices) 
        int n = prices.length ;
        int [][] dp = new int [n][2] ;
        dp[0][0] = 0;
        dp[0][1] = -prices[0] ;

        for(int i=1; i<n; i++)
            dp[i][0] = Math.max(dp[i-1][0], dp[i-1][1] + prices[i]) ;
            dp[i][1] = Math.max(dp[i-1][1],  dp[i-1][0] - prices[i]) ;
        
        return dp[n-1][0] ;
    


9-买股票的最佳时机III
题目链接:题目链接戳这里!!!

思路1:每次记录四个变量即可
firstBuy:第一次买可以获得的最大利润
firstSell:第一次卖出可以获得的最大利润
secondBuy:第二次买入可以获得的最大利润
secondSell:第二次卖出可以获得的最大利润

AC代码如下:

class Solution 
    public int maxProfit(int[] prices) 
        int firstBuy = Integer.MIN_VALUE ; //第一次买入可获得的最大利润
        int secondBuy = Integer.MIN_VALUE ;//第二层买入可获得的最大利润
        int firstSell = 0, secondSell = 0 ; //第一次和第二次卖出可获得的最大利润
        for(int i=0; i<prices.length; i++)
            firstBuy = Math.max(firstBuy, -prices[i]) ;
            firstSell = Math.max(firstSell, firstBuy+prices[i]) ;
            secondBuy = Math.max(secondBuy, firstSell-prices[i]) ;
            secondSell = Math.max(secondSell, secondBuy+prices[i]) ;
        
        return secondSell ;
    


当然上面的方式比较好理解,但是不是标准话的动态规划表示形式,把四个变量换成一维数组就可以。

AC代码如下:

class Solution 
    public int maxProfit(int[] prices) 
        int [] dp = new int [4] ;
         dp[0] = -prices[0] ; //第一次买入可获得的最大利润
         dp[2] = -prices[0];//第二次买入可获得的最大利润
    
        for(int i=0; i<prices.length; i++)
            dp[0] = Math.max(dp[0], -prices[i]) ;
            dp[1] = Math.max(dp[1], dp[0]+prices[i]) ;
            dp[2] = Math.max(dp[2], dp[1]-prices[i]) ;
            dp[3] = Math.max(dp[3], dp[2]+prices[i]) ;
        
        return dp[3] ;
    


10-最大正方形
题目链接:题目链接戳这里!!!

思路:dp[i][j]表示以第i行j列为右下角能构成侧最大正方形边长,每次当矩阵中的值为1时,可以得到的递推表达式如下:
dp[i][j] = Math.min(Math.min(dp[i-1][j-1], dp[i-1][j]), dp[i][j-1]) + 1 ;
然后依次比较所有dp[i][j],找到最大值就可以。
max = Math.max(max, dp[i][j]) ;

class Solution 
    public int maximalSquare(char[][] matrix) 
        //dp[i][j]表示以第i行第j列为右下角能构成的最大正方形边长
        int m = matrix.length ;
        int n = matrix[0].length ;
        int max = 0 ;
        int [][] dp = new int [m+1][n+1] ;
 
        for(int i=1; ileetcode之动态规划刷题总结3

leetcode之动态规划刷题总结8

leetcode之动态规划刷题总结6

leetcode之动态规划刷题总结7

LeetCode刷题笔记-动态规划-day5

LeetCode刷题笔记-动态规划-day5