题目
解题
注意当 n = 0 时,返回值为 1。
以下题目解题方法相同,区别点是根据题干,动态转移方程会有差异。
题目 | 解题 |
---|---|
面试题 08.01. 三步问题 | 三步问题题解 |
剑指 Offer 10- I. 斐波那契数列 | 斐波那契数列题解 |
70. 爬楼梯 | 爬楼梯 |
剑指Offer 10- II 青蛙跳台阶问题 | 青蛙跳台阶问题 |
解题一:动态规划
// javascript
var numWays = function(n) {
const vec = [1, 1, 2];
if (n < 3) return vec[n];
const MOD = 1e9 + 7;
let p = 1, q = 2, r;
for (let i = 3; i <= n; ++i) {
r = (p + q) % MOD;
p = q;
q = r;
}
return r;
};
解题二:矩阵快速幂
[ F ( n − 1 ) F ( n ) ] = [ 0 1 1 1 ] n − 1 ∗ [ F ( 0 ) F ( 1 ) ] \begin{bmatrix} F(n-1) \\ F(n) \end{bmatrix} = {\begin{bmatrix} 0 & 1 \\ 1 & 1\end{bmatrix}}^{n-1} * \begin{bmatrix} F(0) \\ F(1) \end{bmatrix} [F(n−1)F(n)]=[0111]n−1∗[F(0)F(1)]
// javascript
var numWays = function(n) {
const vec = [1, 1];
if (n < 2) return vec[n];
const A = [[0, 1], [1, 1]];
const Amul = matpow(A, n - 1);
const res = matmul(Amul, [[vec[0], 0], [vec[1], 0]]);
return res[1][0];
};
const matpow = (a, n) => {
let ret = [[1, 0], [0, 1]];
// 以 7 (0b111) 为例,a^7 = a^4 + a^2 + a^1
while (n > 0) {
if ((n & 1) === 1) {
ret = matmul(ret, a);
}
n >>= 1;
a = matmul(a, a);
}
return ret;
};
const matmul = (a, b) => {
const m1 = a.length, n1 = a[0].length;
const m2 = b.length, n2 = b[0].length;
if (n1 !== m2) {
throw new Error('these 2 matrix can not be multiplied!');
}
const MOD = BigInt(1e9 + 7);
// 初始化时要用 BigInt 类型 => 数字后面加 n
const res = new Array(m1).fill(0n).map(() => new Array(n2).fill(0n));
for (let i = 0; i < m1; ++i) {
for (let j = 0; j < n2; ++ j) {
for (let k = 0; k < n1; ++k) {
res[i][j] += BigInt(a[i][k]) * BigInt(b[k][j]);
}
// 结果取模
res[i][j] %= MOD;
}
}
return res;
};