代码随想录算法训练营第三十一天 | leetcode:斐波那契数,爬楼梯,使用最小花费爬楼梯

动态规划理论基础

动态规划题型

什么是动态规划

代码随想录算法训练营第三十一天 | leetcode:斐波那契数,爬楼梯,使用最小花费爬楼梯

  1. 动态规划,英文:Dynamic Programming,简称DP。动态规划中每一个状态一定是由上一个状态推导出来的,这一点就区分于贪心,贪心没有状态推导,而是从局部直接选最优的。
  2. 动态规划解题步骤
    • 确定dp数组(dp table)以及下标的含义
    • 确定递推公式
    • dp数组如何初始化
    • 确定遍历顺序
    • 举例推导dp数组

509. 斐波那契数

解题方法

根据题目给出的递推公式:F(n) = F(n - 1) + F(n - 2)可得,第0个斐波那契数是0,第1个斐波那契数是1,第2个是1,第3个是3,第4个是4,第5个….. 用更浅显的语言表达就是当前位置的数等于前两个数相加。

  1. 第一步确定dp数组的含义:dp[i] 代表第i个斐波那契数
  2. 递推公式::F(n) = F(n - 1) + F(n - 2) 其中 n > 1
  3. 初始化dp数组:$dp[0] = 0; $dp[1] = 1; $dp[$i] = $dp[$i-1] + $dp[$i - 2];
  4. 遍历顺序:因为当前位置的斐波那契数依赖于前两个数,所以遍历顺序是从前往后。
  5. 举例推导dp数组:代入 i ,打印dp数组,验证是否符合要求

code

动态规划常规解法

class Solution {
    /**
     * @param Integer $n
     * @return Integer
     */
    function fib($n) {
        //dp[i] 代表第i个斐波那契数
        //题目已给出递推公式:F(n) = F(n - 1) + F(n - 2) 其中 n > 1
        if($n < 2) return $n;
        //初始化dp数组
        $dp[0] = 0; $dp[1] = 1;
        //遍历
        for($i = 2; $i <= $n; $i++){
            $dp[$i] = $dp[$i-1] + $dp[$i - 2];
        }
        return $dp[$n];
    }
}

复杂度

时间复杂度

O(n)

空间复杂度

O(n)

动态规划节省空间解法

class Solution {
    /**
     * @param Integer $n
     * @return Integer
     */
    function fib($n) {
        if($n < 2) return $n;
        $a = 0; $b = 1;
        for($i = 2; $i <= $n; $i++){
            $sum = $a + $b;
            $a = $b;
            $b = $sum;
        }
        return $b;
    }
}

复杂度

时间复杂度

O(n)

空间复杂度

O(1)

递归解法(耗时最久)

class Solution {
    /**
     * @param Integer $n
     * @return Integer
     */
    function fib($n) {
        if($n < 2) return $n;
        return $this->fib($n-1) + $this->fib($n - 2);
    }
}

复杂度

时间复杂度

O(2^n)

空间复杂度

O(n),算上了编程语言中实现递归的系统栈所占空间

70. 爬楼梯

解题方法

把前5个阶梯的爬法列出来,就可以得到推导公式n = (n-1) + (n-2);但是这里和斐波那契题解不一样的地方是这里不需要考虑n = 0的情况,因为1 <= n <= 45。

  1. 第一步确定dp数组的含义:dp[i] 代表到第 i 个阶梯,一共有dp[i]种爬法。
  2. 递推公式:F(n) = F(n - 1) + F(n - 2) 其中 n > 2
  3. 初始化dp数组:$dp[1] = 1; $dp[2] = 2; $dp[$i] = $dp[$i-1] + $dp[$i - 2];
  4. 遍历顺序:因为当前位置的爬法依赖于前两个种,所以遍历顺序是从前往后。
  5. 举例推导dp数组:代入 i ,打印dp数组,验证是否符合要求

code

动态规划常规解法

class Solution {

    /**
     * @param Integer $n
     * @return Integer
     */
    function climbStairs($n) {
        //把前5个阶梯的爬法列出来,就可以得到推导公式n = (n-1) + (n-2)
        if($n < 3) return $n;
        $dp[1] = 1; $dp[2] = 2;
        for($i = 3; $i <= $n; $i++){
            $dp[$i] = $dp[$i-1] + $dp[$i-2];
        }
        //print_r($dp);
        return $dp[$n];
    }
}

复杂度

时间复杂度

O(n)

空间复杂度

O(n)

动态规划节省空间解法

class Solution {
    /**
     * @param Integer $n
     * @return Integer
     */
    function climbStairs($n) {
       if($n < 3) return $n;
        $a = 1; $b = 2;
        for($i = 3; $i <= $n; $i++){
            $sum = $a + $b;
            $a = $b;
            $b = $sum;
        }
        return $b;
    }
}

复杂度

时间复杂度

O(n)

空间复杂度

O(1)

746. 使用最小花费爬楼梯

解题方法

根据题意我们可以从第0个阶梯或者第1个阶梯开始,那么$dp[0] = 0,$dp[1] = 0。因为在当前位置没有移动,不花费体力。从 下标 0 下标1 开始跳就要花费体力了。可以有两个途径得到dp[i],一个是dp[i-1] 一个是dp[i-2]。而题目要求最小,则取最小值即可。

  • dp[i - 1] 跳到 dp[i] 需要花费 dp[i - 1] + cost[i - 1]。
  • dp[i - 2] 跳到 dp[i] 需要花费 dp[i - 2] + cost[i - 2]。
  1. 第一步确定dp数组的含义:到达第i台阶所花费的最少体力为dp[i]。
  2. 递推公式:$dp[$i] = min($dp[$i-1] + $cost[$i-1],$dp[$i-2] + $cost[$i-2]); 其中 n > 1
  3. 初始化dp数组:$dp[0] = 0; $dp[1] = 0; $dp[$i] = min($dp[$i-1] + $cost[$i-1],$dp[$i-2] + $cost[$i-2]);
  4. 遍历顺序:因为当前位置的爬法依赖于前两个种,所以遍历顺序是从前往后。
  5. 举例推导dp数组:代入 i ,打印dp数组,验证是否符合要求

code

动态规划常规解法

class Solution {
    /**
     * @param Integer[] $cost
     * @return Integer
     */
    function minCostClimbingStairs($cost) {
        $dp[0] = $dp[1] = 0;
        for($i = 2; $i <= count($cost); $i++){
            $dp[$i] = min($dp[$i-1] + $cost[$i-1],$dp[$i-2] + $cost[$i-2]);
        }
        return end($dp);
    }
}

复杂度

时间复杂度

O(n)

空间复杂度

O(n)

动态规划节省空间解法

class Solution {
    /**
     * @param Integer[] $cost
     * @return Integer
     */
    function minCostClimbingStairs($cost) {
        $dp0 = $dp1 = 0;
        for($i = 2; $i <= count($cost); $i++){
            $min = min($dp1 + $cost[$i-1],$dp0 + $cost[$i-2]);;
            $dp0 = $dp1;
            $dp1 = $min;
        }
        return $dp1;
    }
}

复杂度

时间复杂度

O(n)

空间复杂度

O(1)

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!