算法Day38 | 动态规划,509. 斐波那契数, 70. 爬楼梯, 746. 使用最小花费爬楼梯

Day38

    • 动态规划
    • 509. 斐波那契数
    • 70. 爬楼梯
    • 746. 使用最小花费爬楼梯

动态规划

动态规划是一种解决问题的算法思想。它通常用于优化问题,其中要求找到一个最优解或最大化(最小化)某个目标函数。

动态规划的核心思想是将问题分解成更小的子问题,并通过存储子问题的解来避免重复计算。这样,可以通过解决子问题来构建原始问题的解。动态规划通常适用于具有重叠子问题和最优子结构特性的问题。

动态规划的一般步骤如下:

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

动态规划数学归纳法的异同:

动态规划 数学归纳法
目的 解决优化问题 证明命题的正确性
解决方法 将问题划分为子问题,通过存储子问题的解避免重复计算 将问题归纳到更小的情况进行证明
焦点 求解问题的过程 问题的正确性证明
应用领域 计算机科学、运筹学、经济学等 数学、逻辑学等
相同之处 都通过将问题分解为更小的部分来解决 都需要基于已知情况来推导出新的结论

509. 斐波那契数

题目链接:509. 斐波那契数

class Solution {
public:
    int fib(int n) {
        vector<int> dp{0, 1};
        dp.resize(n + 1);
        for (int i = 2; i < n + 1; ++i) {
            dp[i] = dp[i - 2] + dp[i - 1];
        }
        return dp[n];
    }
};

根据公式 F ( n ) = F ( n − 1 ) + F ( n − 2 ) F(n) = F(n - 1) + F(n -2) F(n)=F(n1)+F(n2),本题其实只需要维护两个变量就可以求出。

class Solution {
public:
    int fib(int n) {
        if (n <= 1) return n;
        int val1 = 0, val2 = 1;
        while(n-- >= 2) {
            int sum = val2 + val1;
            val1 = val2;
            val2 = sum;
        }
        return val2;
    }
};

70. 爬楼梯

题目链接:70. 爬楼梯
1个台阶,有1种方法;2个台阶,有2种方法;3个台阶,有1+2种方法。

3个台阶就是1个台阶和2个台阶的总和。为什么?因为题目就让迈1个或2个台阶,因此到3阶,从1阶迈两步,从2阶迈一步,因此是1阶和2阶的总和。这就是将问题分解成更小的子问题,并通过存储子问题的解来避免重复计算

同理,4个台阶,通过3阶迈一步,2阶迈两步,有2+3种方法。
… …

dp 数组的含义:到达第 i 阶,有 dp[i] 种方法
递推公式:dp[i] = dp[i -1] + dp[i - 2]
初始化:dp[1] = 1; dp[2] = 2dp[0]没有意义,但是为了满足递推公式,可以初始化为1)
遍历顺序:从前向后

class Solution {
public:
    int climbStairs(int n) {
        vector<int> dp{1, 1, 2};
        dp.resize(n + 1);
        for (int i = 3; i < n + 1; ++i) {
            dp[i] = dp[i - 2] + dp[i - 1];
        }
        return dp[n];
    }
};

当然,因为是斐波那契数列,也可以维护只两个变量来完成。


746. 使用最小花费爬楼梯

题目链接:746. 使用最小花费爬楼梯
dp 数组的含义:到达第 i 阶,所需要的花费为 dp[i]
递推公式:dp[i] = min(dp[i -1] + cost[i - 1], dp[i - 2] + cost[i - 2])
初始化:根据题意可知dp[0] = 0; dp[1] = 0
遍历顺序:从前向后

class Solution {
public:
    int minCostClimbingStairs(vector<int>& cost) {
        vector<int> dp{0, 0};
        dp.resize(cost.size() + 1);
        for (int i = 2; i < cost.size() + 1; ++i) {
            dp[i] = min(dp[i - 1] + cost[i - 1], dp[i - 2] + cost[i - 2]);
        }
        return dp.back();
    }
};

你可能感兴趣的:(刷题日志,动态规划,算法,leetcode)