70 爬楼梯

在这里插入图片描述
解题思路一:(动态规划)
\qquad 假设F(n)返回的是爬n阶的所有方法个数,由题可知,每次可以爬1-2级台阶,那么可以得到:
\qquad \qquad \qquad \qquad \qquad F(n) = F(n - 1) + F(n - 2)
\qquad 我们可以通过列表的方法记录每个F(n)的值,后面的数只要不断查表并将其相加就可以了。

\qquad 虽然这个方法的时间复杂度已经是O(N),但空间复杂度可以进一步优化。观察计算公式,其实并不需要记录每个F(n)的值,只记录F(n - 1)F(n - 2)的值就足够了,这样空间复杂度达到了O(1)

	int climbStairs(int n) {
        int a = 0, b = 0, c = 1;
        for(int i = 1; i <= n; i++)
        {
            a = b; 
            b = c;
            c = a + b;
        }
        return c;
    }

解题思路二:(快速幂)
\qquad 需要将公式F(n) = F(n - 1) + F(n - 2)转换为矩阵计算的形式,即:
在这里插入图片描述
递推回去可以得到:
在这里插入图片描述
令: M = [ 1 1 1 0 ] M = \begin{bmatrix} 1 & 1 \\ 1 & 0 \end{bmatrix} M=[1110]只要求出 M n M^n Mn,就能得到F(n)的值。快速幂快就快在对 M n M^n Mn的计算上,把n看做一个二进制数表示(如1101),每一位都有一个“基数” = M 2 i M^{2^i} M2i,只要将二进制表示中为1的数位对应的“基数”相乘,就可以得到 M n M^n Mn。而每一位的“基数”可以前一位的“基数”不断平方得到,即: M 2 i − 1 ∗ M 2 i − 1 = M 2 ∗ 2 i − 1 = M 2 i M^{2^{i-1}} * M^{2^{i-1}} = M^{2*2^{i-1}} = M^{2^i} M2i1M2i1=M22i1=M2i,这样将时间复杂度可以达到O(log N)

\qquad 其中,矩阵计算可以套用模版(m为左矩阵的列数): M [ i ] [ j ] = ∑ k = 0 m − 1 a [ i ] [ k ] ∗ b [ k ] [ j ] M[i][j] = \sum_{k=0}^{m-1} a[i][k]*b[k][j] M[i][j]=k=0m1a[i][k]b[k][j]

	typedef long long ll;
    vector<vector<ll>> matrixMlt(vector<vector<ll>> & a, vector<vector<ll>> &b)
    {
        vector<vector<ll>> c(2, vector<ll>(2));
        for(int i = 0; i < 2; i++)
        {
            for(int j = 0; j < 2; j++)
            {
                c[i][j] = a[i][0]*b[0][j] + a[i][1]*b[1][j];
            }
        }

        return c;
    }

    int climbStairs(int n)
    {
        vector<vector<ll>> ans = {{1, 0}, {0, 1}};
        vector<vector<ll>> std = {{1, 1}, {1, 0}};
        while(n > 0)
        {
            if(n & 1 == 1)
            {
                ans = matrixMlt(ans, std);
            }
            std = matrixMlt(std, std);
            n >>= 1;
        }
        return ans[0][0];
    }

一点拓展:
\qquad 快速幂可以用在一些齐次线性递推式中,形如 f ( n ) = ∑ i = 1 m a i f ( n − i ) f(n) = \sum_{i=1}^m a_if(n-i) f(n)=i=1maif(ni),都可以列出其 M M M
[ a 1 a 2 a 3 ⋯ a m 1 0 0 ⋯ 0 0 1 0 ⋯ 0 ⋮ ⋮ ⋮ ⋱ ⋮ 0 0 0 ⋯ 1 ] \begin{bmatrix} a_1 & a_2 & a_3 & \cdots & a_m \\ 1 & 0 & 0 & \cdots & 0 \\ 0 & 1 & 0 & \cdots & 0 \\ \vdots & \vdots & \vdots & \ddots &\vdots \\ 0 & 0& 0 & \cdots & 1 \end{bmatrix} a1100a2010a3000am001

\qquad 如果不满足齐次线性递推式,可以构建 g ( x ) g(x) g(x),通过添加(x-1)、(x-2) ... (x-m)凑出如上形式,但其实不太常用,了解就好了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值