剑指 Offer 10- II. 青蛙跳台阶问题(70. 爬楼梯)
题目:
思路:
【1】动态规划,利用F(N)=F(N-1)+F(N-2)的公式。
【2】矩阵快速幂(重点难以理解)
【3】通项公式:根据递推方程 f(n)=f(n−1)+f(n−2),我们可以写出这样的特征方程:x^2 = x + 1。 【但这种只限于爬楼梯,因为如果要除某个数的话直接拿结果除是不合适的】(需要重点理解)
代码展示:
通项公式:
//时间0 ms击败100% //内存38.1 MB击败86% //这种是最优的因为通过数学拿到公式后可以减少很多步骤 class Solution { public int climbStairs(int n) { double sqrt5 = Math.sqrt(5); double fibn = Math.pow((1 + sqrt5) / 2, n + 1) - Math.pow((1 - sqrt5) / 2, n + 1); return (int) Math.round(fibn / sqrt5); } }
矩阵快速幂的方式:
//时间0 ms击败100% //内存38.5 MB击败28.24% class Solution { static final int MOD = 1000000007; public int numWays(int n) { int[][] a = {{1, 1}, {1, 0}}; int[][] res = pow(a, n); return res[0][0]; } public int[][] pow(int[][] a, int n) { int[][] ret = {{1, 0}, {0, 1}}; while (n > 0) { if ((n & 1) == 1) { ret = mul(ret, a); } n >>= 1; a = mul(a, a); } return ret; } public int[][] mul(int[][] a, int[][] b) { int[][] c = new int[2][2]; for (int i = 0; i < 2; ++i) { for (int j = 0; j < 2; ++j) { c[i][j] = (int) (((long)a[i][0] * b[0][j] + (long)a[i][1] * b[1][j]) % MOD); } } return c; } } //时间0 ms击败100% //内存38.4 MB击败34.11% //时间复杂度:同快速幂,O(logn)。 //空间复杂度:O(1)。 class Solution { public int climbStairs(int n) { int[][] q = {{1, 1}, {1, 0}}; int[][] res = pow(q, n); return res[0][0]; } public int[][] pow(int[][] a, int n) { int[][] ret = {{1, 0}, {0, 1}}; while (n > 0) { if ((n & 1) == 1) { ret = multiply(ret, a); } n >>= 1; a = multiply(a, a); } return ret; } public int[][] multiply(int[][] a, int[][] b) { int[][] c = new int[2][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; } }
简单的动态规划,利用F(N)=F(N-1)+F(N-2)的公式:
//时间0 ms击败100% //内存38.2 MB击败63.73% //时间复杂度:循环执行 n 次,故时间复杂度为 O(n)。 //空间复杂度:这里只用了常数个变量作为辅助空间,故空间复杂度为 O(1)。 class Solution { public int numWays(int n) { int a1 = 1 , a2 = 2; if (n == 1 || n == 0) return a1; if (n == 2) return a2; int res = 1; for (int i = 3;i <= n; i++){ res = (a1 + a2)%1000000007; a1 = a2; a2 = res; } return res; } } //时间0 ms击败100% //内存38 MB击败92.49% class Solution { public int climbStairs(int n) { int a1 = 1 , a2 = 2; if (n == 1 || n == 0) return a1; if (n == 2) return a2; int res = 1; for (int i = 3;i <= n; i++){ res = (a1 + a2); a1 = a2; a2 = res; } return res; } }