Leetcode[70] 爬楼梯 dp&快速幂

Leetcode[70] 爬楼梯 dp&快速幂

爬楼梯

Category Difficulty Likes Dislikes
algorithms Easy (50.75%) 1330 -
Tags

dynamic-programming

Companies

adobe | apple

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

知识点

动态规划

容易得到 f(n) = f(n - 1) + f(n - 2)

直接递归会超时,故用空间换时间,时间复杂度为O(n)。

DP代码

/*
 * @lc app=leetcode.cn id=70 lang=cpp
 *
 * [70] 爬楼梯
 */
#include <bits/stdc++.h>
using namespace std;
// @lc code=start

class Solution
{
public:
    int climbStairs(int n)
    {
        if (n <= 2)
        {
            return n;
        }
        int a = 1, b = 2;
        int c;
        for (int i = 3; i <= n; i++)
        {
            c = a + b;
            a = b;
            b = c;
        }
        return c;  
    }
};
// @lc code=end

(矩阵)快速幂

不妨先来复习一下快速幂,假设现在我们需要计算a11

比较麻烦的方法是计算a * a * …… * a,需要做11次乘法。

如果将11转化成二进制,(11)10 = (1011)2,a11便可以写成a ^ (23+21+20)。

于是将a11转化为a ^ 23 * a ^ 21 *a ^ 20,只需要做3次乘法。

如果要计算an,使用麻烦方法的时间复杂度为O(n),而使用快速幂的时间复杂度为O(logn)。

double quickPow(double x, int n)
{
    double ans = 1.0;
    while (n)
    {
        if (n & 1)	//取低位
        {
            ans = ans * x;
        }
        n >>= 1;	//右移一位
        x = x * x;	//a ^ (2 ^ m)
    }
    return ans;
}

齐次线性递推式的求解

在这里插入图片描述
对于本题,我们可以构建这样的递推关系:
在这里插入图片描述
易得
在这里插入图片描述

下面给出本题用矩阵快速幂求解的代码,时间复杂度为O(logn)

矩阵快速幂代码

/*
 * @lc app=leetcode.cn id=70 lang=cpp
 *
 * [70] 爬楼梯
 */
#include <bits/stdc++.h>
using namespace std;
// @lc code=start

class mat22
{
public:
    long long m[2][2];

public:
    mat22(long long a, long long b, long long c, long long d)
    {
        m[0][0] = a;
        m[0][1] = b;
        m[1][0] = c;
        m[1][1] = d;
    }
    void multi(mat22 m1)
    {
        long long a1 = m[0][0], b1 = m[0][1], c1 = m[1][0], d1 = m[1][1];
        long long a2 = m1.m[0][0], b2 = m1.m[0][1], c2 = m1.m[1][0], d2 = m1.m[1][1];
        m[0][0] = a1 * a2 + b1 * c2;
        m[0][1] = a1 * b2 + b1 * d2;
        m[1][0] = c1 * a1 + d1 * c2;
        m[1][1] = c1 * b2 + d1 * d2;
    }
};
class Solution
{
public:
    mat22 quickPow(long long n)
    {
        mat22 ans = mat22(1, 0, 0, 1);
        mat22 a = mat22(1, 1, 1, 0);
        while (n)
        {
            if (n & 1)
            {
                ans.multi(a);
            }
            n >>= 1;
            a.multi(a);
        }
        return ans;
    }
    int climbStairs(int n)
    {
        if (n == 2)
            return 2;
        if (n == 1)
            return 1;
        else
        {
            mat22 matx = quickPow(n - 2);
            return matx.m[0][0] * 2 + matx.m[0][1];
        }
        
    }
};
// @lc code=end

猜你喜欢

转载自blog.csdn.net/weixin_44458659/article/details/110086455