leetcode_动态规划相关

本文详细探讨了动态规划的概念和应用,通过多个经典的编程题目,如爬楼梯、三角形最小路径和、最大子序和等,阐述了动态规划的解决思路和状态转移方程。动态规划是一种自底向上的解决问题的方法,通过避免重复计算子问题来优化递归过程。文中还提到了动态规划在解决最短路径问题中的应用,如Dijkstra算法。
摘要由CSDN通过智能技术生成

动态规划

递归:是自上而下的解决问题,假设最基本的问题已经解决了,在递归过程中可能会出现许多重复的子问题的求解过程,可以采用记忆化搜索的方式来优化重复子问题的不足

动态规划:是自底向上的解决一个问题,将原问题拆解成若干子问题,同时保证子问题的答案,使得每个子问题只求解一次,最终获得原问题的答案

动态规划 ==> 出现重叠子问题、最优子结构 ==> 采用记忆化搜索(自顶向下) 或  动态规划(自底向上)

动态规划思路:明确状态(dp数组中存储的值的具体含义)==> 状态初始化 ==> 状态转移方程求解

状态:即函数的定义 (dp数组中存储的值的具体含义);

状态转移:根据对状态的定义,确定状态的转移,dp[i] 如何由 dp[j] (j<i) 获得

 

70. 爬楼梯

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。
每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

示例 1:
输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1.  1 阶 + 1 阶
2.  2 阶

示例 2:
输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1.  1 阶 + 1 阶 + 1 阶
2.  1 阶 + 2 阶
3.  2 阶 + 1 阶

class Solution {
    public int climbStairs(int n) {
        //爬第k阶台阶,可以是从第k-1阶爬上来,也可以是从第k-2阶爬上来,所以,爬上第k阶楼梯的方法为爬上第k-1阶楼梯的方法+爬上第k-2阶楼梯的方法
        //动态规划实现
        if(n==1){
            return 1;
        }
        
        int[] dp = new int[n+1];  //dp[k]为爬上第k阶楼梯的方法数
        dp[1] = 1;
        dp[2] = 2;
        
        for(int k=3; k<=n; k++){
            dp[k] = dp[k-2]+dp[k-1];
        }
        
        return dp[n];        
    }
}

 

120. 三角形最小路径和

给定一个三角形,找出自顶向下的最小路径和。每一步只能移动到下一行中相邻的结点上。
例如,给定三角形:

[
     [2],
    [3,4],
   [6,5,7],
  [4,1,8,3]
]
自顶向下的最小路径和为 11(即,2 + 3 + 5 + 1 = 11)。

说明:
如果你可以只使用 O(n) 的额外空间(n 为三角形的总行数)来解决这个问题,那么你的算法会很加分。

思路:dp解法,开辟一个int[] dp ,用以记录某一层每个元素到最底层的最短距离,复用这个dp数组。

class Solution {
    public int minimumTotal(List<List<Integer>> triangle) {
        
        int n = triangle.size();
        
        //dp[i]表示某一层第i个元素到最底层的最短距离
        //从最底层开始,向上推,每一层都要更新dp[i]中的值,直到最顶层只有一个元素,则dp[0]即为所求
        int[] dp = new int[triangle.get(n-1).size()]; 
        
        //初始化,最底层每个元素到最底层的的距离就是最底层每个元素本身的值
        for(int i=0; i<triangle.get(n-1).size(); i++){
            dp[i] = triangle.get(n-1).get(i);
        }
        
        //外层循环负责向上更新层数, 内层循环负责更新当前层每个元素到最底层的最小距离
        for(int k=n-2; k>=0; k--){
            //获得当前层的list,根据当前层list中的元素值以及下一层dp数组进行更新,使其dp成为当前层dp数组
            List<Integer> cur = triangle.get(k);
            for(int i=0; i<cur.size(); i++){
                dp[i] = cur.get(i)+Math.min(dp[i], dp[i+1]);
            }
        }
        
        return dp[0];
    }
}

 

64.最小路径和

给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小。

说明:每次只能向下或者向右移动一步。

示例:

输入:
[
  [1,3,1],
  [1,5,1],
  [4,2,1]
]
输出: 7
解释: 因为路径 1→3→1→1→1 的总和最小。

class Solution {
    public int minPathSum(int[][] grid) {
        if(grid.length == 0 || grid[0].length == 0){
            return 0;
        }
        
        int m = grid.length, n = grid[0].length;
        
        // 采用二维数组 dp[][], dp[i][k]表示走到grid[i][k]时的最短路径, 则 dp[i][k] = min(dp[i-1][k], dp[i][k-1])+grid[i][k]
        // 由于考虑第i行的时候,前i-2行的数据都不需要的,可以复用一个一维数组即可
        // dp[k] = min(dp[k-1], dp[k])+grid[i][k], 其中左侧的 dp[k]即dp[i][k], 右侧的 dp[k]即dp[i-1][k], 右侧的dp[k-1]即dp[i][k-1]
        int[] dp = new int[n];  
        
        for(int i=0; i<m; i++){
            for(int k=0; k<n; k++){
                if(k==0){
                    dp[k] = dp[k]; 
                }else if(i==0){
                    dp[k] = dp[k-1];
                }else{
                    dp[k] = Math.min(dp[k], dp[k-1]);
                }
                
                dp[k] += grid[i][k];
            }
        }
        
        return dp[n-1];      
    }
}

62.不同路径

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为“Start” )。

机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为“Finish”)。

问总共有多少条不同的路径?

 

例如,上图是一个7 x 3 的网格。有多少可能的路径?

说明:m 和 n 的值均不超过 100。

示例 1:

输入: m = 3, n = 2
输出: 3
解释:
从左上角开始,总共

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值