动态规划练习(一)

参考 大佬的学习笔记 题解
题目全部基于leetcode

解题步骤

  1. 确定dp数组(dp table)以及下标的含义
  2. 确定递推公式
  3. dp数组如何初始化
  4. 确定遍历顺序
  5. 举例推导dp数组

当前进度基础篇,持续更新。。。

基础篇

熟悉动态规划的解题思路,理解解题步骤

509.斐波那契数

题目描述

斐波那契数 (通常用 F(n) 表示)形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:
F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1
给定 n ,请计算 F(n) 。

解题步骤

  1. 确定dp数组(dp table)以及下标的含义
    dp:斐波那契数列
    dp[i]:第i个数的斐波那契数值
  2. 确定递推公式
    dp[i] = dp[i-1] + dp[i-2]
  3. dp数组如何初始化
    dp[0] = 0
    dp[1] = 1
  4. 确定遍历顺序
    由推导公式dp[i] = dp[i-1] + dp[i-2] 可知
    是由前数计算出后数的,顺序为从前往后遍历
  5. 举例推导dp数组
    0 1 1 2 3 5 8 13

实现代码

class Solution {
    public int fib(int n) {
        if (n<2) {
            return n;
        }
        return fib(n-1) + fib(n-2);
    }
}

70. 爬楼梯

题目描述

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

解题步骤

  1. 确定dp数组(dp table)以及下标的含义
    dp[i]:爬到第i层楼梯,有dp[i]种方法
  2. 确定递推公式

    i-2阶爬2个台阶,可达到i
    i-1阶爬1个台阶,可达到i
    可知
    dp[i] = dp[i-1] + dp[i-2]
  3. dp数组如何初始化
    爬上1阶,只有1种方法
    dp[1] = 1
    爬上2阶,有2种方法(1+1;2)
    dp[2] = 2
  4. 确定遍历顺序
    由推导公式dp[i] = dp[i-1] + dp[i-2] 可知
    是由前数计算出后数的,顺序为从前往后遍历
  5. 举例推导dp数组
    1 2 3 5 8 13

实现代码

class Solution {
    public int climbStairs(int n) {
        if (n < 3) {
            return n;
        }
        return climbStairs(n-1) + climbStairs(n-2);
    }
}

上面的递归方法,在leetcode会超出时间限制,可尝试下面的方法

class Solution {
    public int climbStairs(int n) {
        int dp0 = 0, dp1 = 0, result = 1;
       for (int i = 1; i <= n; ++i) {
           dp0 = dp1;
           dp1 = result;
           result = dp0 + dp1;
       }
       return result;
    }
}

746. 使用最小花费爬楼梯

题目描述

给你一个整数数组 cost ,其中 cost[i] 是从楼梯第 i 个台阶向上爬需要支付的费用。一旦你支付此费用,即可选择向上爬一个或者两个台阶。
你可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯。
请你计算并返回达到楼梯顶部的最低花费。

解题步骤

  1. 确定dp数组(dp table)以及下标的含义
    dp[i]:达到第i层楼梯的最低花费
  2. 确定递推公式

    一次可爬1or2台阶,花费有2种
    可知
    dp[i] = dp[i-1] + cost[i-1]

    dp[i] = dp[i-2] + cost[i-2]
    所以
    最低花费
    dp[i] = min(dp[i-1] + cost[i-1], dp[i-2] + cost[i-2])
    这样可保证每次都是最低花费
  3. dp数组如何初始化
    由题目可知
    可以选择从下标为 0 或下标为 1 的台阶开始爬楼梯
    dp[0] = 0
    dp[1] = 0
  4. 确定遍历顺序
    由推导公式可知
    是由前数计算出后数的,顺序为从前往后遍历
  5. 举例推导dp数组

输入:cost = [1,100,1,1,1,100,1,1,100,1]
输出:6
解释:你将从下标为 0 的台阶开始。
-支付 1 ,向上爬两个台阶,到达下标为 2 的台阶。
-支付 1 ,向上爬两个台阶,到达下标为 4 的台阶。
-支付 1 ,向上爬两个台阶,到达下标为 6 的台阶。
-支付 1 ,向上爬一个台阶,到达下标为 7 的台阶。
-支付 1 ,向上爬两个台阶,到达下标为 9 的台阶。
-支付 1 ,向上爬一个台阶,到达楼梯顶部。
总花费为 6 。

实现代码

class Solution {
    public int minCostClimbingStairs(int[] cost) {
        int dp0 =0, dp1 = 0, dpi = 0;
        for (int i=2; i<=cost.length; i++) {
            dpi = Math.min(dp1 + cost[i-1], dp0 + cost[i-2]);
            dp0 = dp1;
            dp1 = dpi;
        }
        return dpi;
    }
}

62. 不同路径

题目描述

一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。
问总共有多少条不同的路径?

示例 1:
动态规划练习(一)_第1张图片
输入:m = 3, n = 7
输出:28

解题步骤

  1. 确定dp数组(dp table)以及下标的含义
    dp[i][j]:到达坐标(i,j)有d[i][j]种方法
  2. 确定递推公式
    由题目
    机器人每次只能向下或者向右移动一步
    可知
    dp[i][j] = d[i-1][j] + d[i][j-1]
  3. dp数组如何初始化
    d[0][j] = 1
    d[i][0] = 1
  4. 确定遍历顺序
    根据推导公式可从左向右遍历
  5. 举例推导dp数组

输入:m = 3, n = 2
输出:3
解释:
从左上角开始,总共有 3 条路径可以到达右下角。
1.向右 -> 向下 -> 向下
2.向下 -> 向下 -> 向右
3.向下 -> 向右 -> 向下

实现代码

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

你可能感兴趣的:(LeetCode,动态规划,算法)