Leetcode[70] 爬楼梯 dp&快速幂
爬楼梯
Category | Difficulty | Likes | Dislikes |
---|---|---|---|
algorithms | Easy (50.75%) | 1330 | - |
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次乘法。
扫描二维码关注公众号,回复:
13147807 查看本文章
![](/qrcode.jpg)
如果将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