代码随想录算法训练营第38天|● 理论基础 ● 509. 斐波那契数 ● 70. 爬楼梯 ● 746. 使用最小花费爬楼梯

509. 斐波那契数

题目链接

动规五部曲:1、确定dp数组的下标以及dp数组的含义:dp[i]表示第i个斐波那契数为dp[i]。

2、确定递推公式。题目中已经给出了,dp(n) = dp(n - 1) + dp(n - 2)

3、dp数组如何初始化。题目也给出了,dp(0) = 0,dp(1) = 1

4、确定遍历顺序。由递推公式可得出是从前向后遍历。当然有的题是从后向前遍历,也有可能两层for循环的先后顺序是有说法的。

5、打印dp数组。

方法一:维护一整个数组,

class Solution {
public:
    int fib(int n) {
        if(n<=1) return n;
        vector dp(n+1);
        //思考的过程应该是先想递推公式,再想初始化,因为初始化是依赖于递推公式的
        dp[0]=0;dp[1]=1;
        int i;
        for(i=2;i<=n;i++){
            dp[i]=dp[i-1]+dp[i-2];
        }
        //return dp[i];//这样写出错,因为跳出for循环之前i又做了一次加加,也就是等于n+1
        return dp[n];
    }
};

错因:1、int i写在了for循环里面,出for循环后没有定义,应该写在外面。

2、最后写成了return dp[i],但此时跳出for循环的时候i已经是n+1了。

注意dp数组的定义方式。

方法二:我们发现求dp[i],只依赖于前两个数值,所以我们没必要维护一整个数组,只需要维护三个变量即可。

class Solution {
public:
    int fib(int n) {
        if(n<=1) return n;//0或1都是返回自己,题目中是从0开始
        int dp[2];
        dp[0]=0;
        dp[1]=1;
        for(int i=2;i<=n;i++){
            int sum=dp[0]+dp[1];
            dp[0]=dp[1];
            dp[1]=sum;
        }
        return dp[1];
    }
};

错因:同样的,返回sum会报未定义的错。

方法三:本题也可以用递归的思路来解。

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

70. 爬楼梯

题目链接

本题的难点在于确定递推公式,确定之后发现和斐波那契数列相同。

1、明确dp数组的下标及数组的含义。dp[i]是到达第i阶有dp[i]种方法。

2、确定递推公式。

3、明确dp数组如何初始化。n是大于0的,dp[0]没有含义。

4、确定遍历顺序。从前向后。

5、打印dp数组。(出问题后打印出来)

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

只需要维护三个变量即可,优化空间复杂度为O(1)。

class Solution {
public:
    int climbStairs(int n) {
        if(n<2) return n;
        int dp[3];//只需要维护三个变量即可,注意这里是dp[3]不是dp[2]
        dp[1]=1;
        dp[2]=2;
        for(int i=3;i<=n;i++){
            int sum=dp[1]+dp[2];
            dp[1]=dp[2];
            dp[2]=sum;
        }
        return dp[2];
    }
};

本题用递归会超时,本题的序列和斐波那契数列略有不同,本题是1、2。。,斐波那契数列是1、1、2。。。

746. 使用最小花费爬楼梯

题目链接

1、确定dp数组的下标以及数组含义:dp[i]是到达i位置的最小花费。

2、确定递推公式。dp[i]=min([dp[i-1]+cost[i-1],dp[i-2]+cost[i-2])。

3、确定dp数组初始化。dp[0]=0,dp[1]=0。

4、确定遍历顺序。从前向后遍历。

5、打印dp数组。

class Solution {
public:
    int minCostClimbingStairs(vector& cost) {
        vector dp(cost.size()+1);//楼梯还要多一层
        dp[0]=0;
        dp[1]=0;
        for(int i=2;i

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