70 爬楼梯 力扣 动态规划 快速幂

70 爬楼梯

记录:

分析: 关键在于公式的理解

f ( x ) = f ( x − 1 ) + f ( x − 2 ) f(x)=f(x-1)+f(x-2) f(x)=f(x1)+f(x2)

  • 一共有x阶台阶,在最后登上第x阶时有两种方案,一种是只需要跨一阶,另一种是需要跨两阶;
  • 而在需要跨一阶时,已经位于第x-1阶;在需要跨两阶时,位于第x-2阶。
  • f(x)代表跨到第x阶时一共有几种方案

滚动数组思想

  class Solution { //第一版AC代码 
   int f[46];
  public:
      int climbStairs(int n) {
          f[0]=f[1]=1;
          for(int i=2;i<=n;i++)
          f[i]=f[i-1]+f[i-2];
          return f[n];
      }
  };
  
  • 由上可看到,申请了46个数组空间,若N较大实际上比较费空间

  • 实际上不需要将过程中每一阶的方案一一存下来,只需要迭代,滚动数组获得n阶时的具体方案数即可。

  • 由低阶的时候不断迭代加进去就可以得到最新的方案值,一直叠加即可,滚动只保持最新的前三个数组的元素即可

  • 修改如下:

class Solution { //滚动数组修改版 
public:
    int climbStairs(int n) {
        int a=b=1,c=1;
        for(int i=2;i<=n;i++)
        {
            c=a+b;//存两者之和 等价于f[i]=f[i-1]+f[i-2];
            a=b; //更新 a 实际就是新f[i-1]=旧f[i]
            b=c;//更新b  实际就是新f[i]=c
        }
        return c;
    }
};
  • 数学思想: 矩阵次幂

    • 适用于n比较大的情况

    • 使用矩阵乘法,考虑到本题涉及到的变量其实只需要2*2大小的矩阵就可,在n较大时,无论是矩阵的空间开销还是矩阵乘法时间开销相加起来总归比n-1次迭代的时间复杂度要有效率,并且此处可用快速幂,使时间复杂度降到
      O ( l o g n ) 其中 n 指的是指数大小 O(logn) 其中n指的是指数大小 O(logn)其中n指的是指数大小

快速幂

  • 理解关键:

    • 将乘法次数减少到一半
    • 确定指数为0时,即初态;
    • 每次相乘其实就是平方,a*a=c c*c=d
    • 若指数为偶数,则只需要递归计算n/2次幂的结果,最后平方
    • 若指数为奇数,则需要递归(n-1)/2次幂的结果,平方后,再乘上一次幂(初态);
    • 所以时间复杂度降为O(log n),参考二叉树
//题解里 C++实现快速幂部分 以矩阵乘法为例
//快速幂可适用于 一维数组、正常一个数皆可,关键在于思想的理解
vector<vector<long long>> multiply(vector<vector<long long>>& a, vector<vector<long long>>& b) {//实现矩阵乘法
        vector<vector<long long>> c(2, vector<long long>(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;
    }
//实现快速幂
    vector<vector<long long>> matrixPow(vector<vector<long long>> a, int n) {
        vector<vector<long long>> ret = { {1, 0}, {0, 1} };//单位矩阵的构造,key
        while (n > 0) {
            if ((n & 1) == 1) {  //很关键,利用与运算,既暂存上一步的结果,又实现指数是奇数则最后再乘上一次初矩阵
                ret = multiply(ret, a);
            }
            n >>= 1; //右移一位,表示n/2;
            a = multiply(a, a); //矩阵平方后更新矩阵,即实现每一次乘法都实现平方
        }
        return ret;
    }

本题 矩阵次幂思想解法 (c++官方题解理解)

class Solution {
public:
    vector<vector<long long>> multiply(vector<vector<long long>> &a, vector<vector<long long>> &b) {
        vector<vector<long long>> c(2, vector<long long>(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;
    }

    vector<vector<long long>> matrixPow(vector<vector<long long>> a, int n) {
        vector<vector<long long>> ret = {{1, 0}, {0, 1}};
        while (n > 0) {
            if ((n & 1) == 1) {
                ret = multiply(ret, a);
            }
            n >>= 1;
            a = multiply(a, a);
        }
        return ret;
    }

    int climbStairs(int n) {
        vector<vector<long long>> ret = {{1, 1}, {1, 0}}; //由本题递归公式得出来的对应的初矩阵
        vector<vector<long long>> res = matrixPow(ret, n);//进行快速幂
        return res[0][0];//取结果矩阵的第一个元素,则为F(n)
    }
};
  • 总结:
    • 关于快速幂的与运算,移位运算如果有计算机组成原理相关底层知识会更有助于理解。
    • 虽然这个题是DP比较基础的题,但是相关的思路可以学习,扎实基础。
  • 22
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值