【每日一题】动态规划(1):爬楼梯

原创
2021/03/23 00:21
阅读数 393

一、动态规划介绍

动态规划 Dynamic Programming,简称 DP,是运筹学的一个分支,它是解决多阶段决策过程最优化的一种数学方法。把多阶段问题变换为一系列相互联系的的单阶段问题,然后逐个加以解决。概念中的相互联系,其实指的就是状态转移方程

很多人觉得DP难,根本原因是因为DP跟一些有固定套路的算法不同(比如DFS、二分法、KMP),它没有实际的步骤规定第一步、第二步来做什么,所以准确来说,DP其实是一种解决问题的思想。

二、题目描述

假设你正在爬楼梯。需要 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 阶

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/climbing-stairs
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

三、题目解析

3.1 思路一:通过单阶段之间的关系确定状态转移方程

当做这个题是,我们可以先简单推演一下。由于一次只能上1个或2个台阶,不难发现,假如我当前在第n个台阶上,那么我上一次应该在第n-1个或者第n-2个台阶上。换句话说,当我知道到达第n-1个台阶的方案数f(n-1),到达第n-2个台阶的方案数是f(n-2)。

那么,我们就自然知道到达第n个阶梯时的方案数,即:f(n)=f(n-1)+f(n-2),这也被称为此问题的状态转移方程

当然,我们还需要确定状态转移方程的边界条件。即几种特殊情况:f(0)=0,f(1)=1,f(2)=2;

确定好状态转移方程和边界条件后,就可以开始敲代码了:

class Solution {
public:
    int climbStairs(int n) {
        int ans = 0;
        if(n==0)
            return 0;
        else if(n==1)
            return 1;
        else if(n==2)
            return 2; 
        else
            return climbStairs(n-1)+climbStairs(n-2);
    }
};

这是一个不断的迭代过程,在实际的提交过程中,很可能超过时间限制。

3.2 思路二:数学归纳法

如果觉得很难直接去找到单阶段问题间的关系,也换一种思考方式。通过数学归纳法来推理出隐藏的状态转移方程。

在不清楚单阶段之间的关系的时候,可以正向推演一遍,可以得到如下表所示的数据: | n | 1 | 2 |3 | 4 | 5 | 6 | ... | | :------------: | :------------: | :------------: | :------------: | :------------: | :------------: | :------------: | :------------: | | f(n) | 1 | 2 |3 |5 | 8 | 13 | ... |

通过观察f(n)的变换,想必大家已经看出了规律。即,前两数之和为第三数的值。

由此,我们就可以写代码啦:

class Solution {
public:
    int climbStairs(int n) {
        int f1=0, f2=1, ans=2;//初始化
        if(n==1)
            return 1;
        else if(n==2)
            return 2;
        else{
            for(int i=1; i<n-1; ++i){
                f1 = f2;
                f2 = ans;
                ans = f1 + f2;
            }
        return ans;
        }
    }
};

代码提交结果:

展开阅读全文
c++
加载中
点击引领话题📣 发布并加入讨论🔥
0 评论
0 收藏
0
分享
返回顶部
顶部