参考资料:《程序员代码面试指南》
70. Climbing Stairs
You are climbing a staircase. It takes n steps to reach the top.
Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?
Example 1:
Input: n = 2
Output: 2
Explanation: There are two ways to climb to the top.
1. 1 step + 1 step
2. 2 steps
思路1:迭代
public int climbStairs2(int n) {
// dp[i] = dp[i-1]+dp[i-2]
// dp[n] is ans
int[] dp = new int[n+1];
dp[0]=1;
dp[1]=1;
if(n>=2)
{
dp[2]=2;
for(int i=3;i<=n;i++)
{
dp[i] = dp[i-1]+dp[i-2];
}
}
return dp[n];
}
思路2:加速矩阵乘法
斐波那契数列的递推公式可以写成矩阵幂乘上递归base case的形式, 从而 把求第n项的问题 转化成了 求矩阵n次幂的问题 (这里具体的问题是求矩阵的n-2次幂),详细推导可以看 《程序员代码面试指南》斐波那契数列篇。
求矩阵n次幂,可以在O(lg n) 的时间内做到,思想是借鉴了 求整数的n次幂的做法, 写出n的二进制形式,只在’1‘位上累乘。详细推导可以看 《程序员代码面试指南》。
宫水三叶姐的矩阵快速幂解法
public int climbStairs(int n) {
if(n<1)
{
return 0;
}
if(n==1||n==2)
{
return n;
}
int[][] base = {{1,1},{1,0}};
int[][] res = matrixPower(base,n-2);
return 2*res[0][0]+res[1][0];
}
public int[][] matrixPower(int[][] base, int k)
{
int n=base.length;
int[][] ele = new int[n][n];
for(int i=0;i<n;i++)
{
ele[i][i]=1;
}
for(;k!=0;k>>=1)
{
if((k&1)==1)
{
ele = matrixMtl(base,ele);
}
base = matrixMtl(base,base);
}
return ele;
}
public int[][] matrixMtl(int[][] ma, int[][] mb)
{
int[][] res = new int[ma.length][ma[0].length];
for(int i=0;i<res.length;i++)
{
for(int j=0;j<res[0].length;j++)
{
for(int k=0;k<ma[0].length;k++)
{
res[i][j]+=ma[i][k]*mb[k][j];
}
}
}
return res;
}
剑指 Offer 10- II. 青蛙跳台阶问题
一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。
答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回 1。
示例 1:
输入:n = 2
输出:2
示例 2:
输入:n = 7
输出:21
示例 3:
输入:n = 0
输出:1
=================
注意迭代写法,还有题目中要求结果取模,记得取模运算的特性,
对和取模 = 对加项分别取模的和 (可能还要再取模),比如:
10%3 = (7+3)%3 = 7%3 + 3%3 = 1+0=1;
class Solution {
public int numWays(int n) {
int a=1,b=1,sum=0;
for(int i=0;i<n;i++){
sum = (a+b)%1000000007;
a = b;
b = sum;
}
return a;
}
}