剑指Offer——跳台阶
题目描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
思路分析
这个问题可以先从简单开始考虑,台阶只有1阶,只有1种跳法,台阶有2阶,有2种跳法:一种两次跳一级;另一种一次跳两级。然后考虑一般情况,当有n级台阶时,将f(n)作为总跳法,第1次跳的时候,可以有两种方法:一是跳一级,此时跳法数目等于后面剩下的n-1级台阶的跳法,即f(n-1);二是跳两级,此时跳法数目等于后面剩下的n-2级台阶的跳法。所以,n级台阶的跳法总数:f(n)=f(n-1)+f(n-2)。从这里可以看出,本题是斐波那契数列的一种变形。
但本题还有一种思路,就是将跳1级与跳2级看成排列组合问题,假设x为跳1级台阶的次数,y为跳2级台阶的次数,于是可知x+2y=n,即x=n-2y,这里可以看作对x与y的排列组合问题,即C(x+y,y)=C(n-y,y)。其中0<=y<=n/2。
代码实现
斐波那契数列实现
1、递归实现
相信很多人第一次接触到斐波那契数列的时候,就是使用递归实现,该实现简单直观,但该算法效率不高,因为递归会反复计算相同的子问题,随着n的增大,计算量也急剧增大,时间复杂度为T(n) = O(1.618 ^ n)。代码如下:
public int recurFib(int n) {
if (n <= 0) {
return 0;
}
if (n == 1 || n == 2) {
return n;
}
return recurFib(n - 1) + recurFib(n - 2);
}
2、递推实现
使用递归实现的算法之所以效率太低,是因为重复计算太多,所以我们可以将中间结果保存,当再次计算的时候先查找一下。但有一种更简单的方法,就是从下向上计算,递归是从上到下计算,上面会依赖下面的值,因此会导致重复计算。我们使用从下往上计算,没有值依赖,算法复杂度就降为O(n)。首先根据f(1)和f(2)算出f(3),f(2)和f(3)算出f(4),以此类推即可算出f(n),实现代码如下:
public int recursiveFib(int n) {
if (n <= 0) {
return 0;
}
if (n == 1 || n == 2) {
return n;
}
int fibN = 0;
int fibNMinusOne = 2;
int fibNMinusTwo = 1;
for (int i = 3; i <= n; i++) {
fibN = fibNMinusOne + fibNMinusTwo;
fibNMinusTwo = fibNMinusOne;
fibNMinusOne = fibN;
}
return fibN;
}
3、矩阵法实现
还有一种矩阵法实现,算法效率最高,时间复杂度为O(logn),该算法是根据下面的公式:

上面的公式可以数学归纳法证明,感兴趣的可以自己搜索一下相关资料,有了上面的公式,就将求解f(n),转换成求二阶矩阵的n次方,然后取结果的第1行第2列即可。如果仅仅是矩阵的乘法,时间复杂度依旧为O(n),但可以使用快速幂的方法求解一个数的乘法。乘方的性质如下:

结合上面两个公式代码如下:
public class Solution {
public int fib(int n) {
if (n <= 0) {
return 0;
}
if (n <= 2) {
return n;
}
int[][] unitMatrix = {{1, 1}, {1, 0}};
int[][] result = matrixPow(unitMatrix, n);
return result[0][0];
}
public int[][] matrixPow(int[][] mat, int n) {
if (n == 1) {
return mat;
} else {
// n是偶数
if ((n & 1) == 0) {
int[][] temp = matrixPow(mat, n >> 1);
return matrixMultiply(temp, temp);
} else {
// n是奇数
int[][] temp = matrixPow(mat, (n - 1) >> 1);
return matrixMultiply(matrixMultiply(temp, temp), mat);
}
}
}
/**
* 矩阵相乘
*
* @param m
* @param n
* @return 结果矩阵,m*n
*/
public int[][] matrixMultiply(int[][] m, int[][] n) {
int rows = m.length;
int cols = n[0].length;
int[][] r = new int[rows][cols];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
r[i][j] = 0;
for (int k = 0; k < m[i].length; k++) {
r[i][j] += m[i][k] * n[k][j];
}
}
}
return r;
}
public static void main(String args[]) {
Solution s = new Solution();
int result = s.fib(3);
System.out.println(result);
}
}
排列组合实现
排列组合是将跳1级数目和跳2级数目看出一个组合,其中x为跳1级数目,y为跳2级数目,且x+2y=n,问题转换成从(x+y)个总跳数中选出y个跳2级的的组合,即C(x+y,y)=C(n-y,y)。实现代码如下:
public class Solution {
public BigDecimal jiecheng(int number) {
BigDecimal result = new BigDecimal(1);
BigDecimal temp;
for (int i = number; i > 0; i--) {
temp = new BigDecimal(i);
result = result.multiply(temp);
}
return result;
}
public int fib(int target) {
if (target <= 0) {
return 0;
}
BigDecimal result = new BigDecimal(0);
// the result is C(n-y,y)
for (int i = 0; i <= target / 2; i++) {
result = result.add(jiecheng(target - i).divide(jiecheng(target - 2 * i).multiply(jiecheng(i))));
}
return result.toBigInteger().intValue();
}
public static void main(String args[]) {
Solution s = new Solution();
int result = s.fib(29);
System.out.println(result);
}
}
剑指Offer——跳台阶的更多相关文章
- (原)剑指offer跳台阶和矩形覆盖
跳台阶 时间限制:1秒空间限制:32768K 题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法. 分析同样为斐波那契数列边形这样的题肯定有公式 设 ...
- 剑指Offer 跳台阶
题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法. 解题思路: f(n)=f(n-1)+f(n-2); f(1)=1,f(2)=2; AC代码 ...
- 用js刷剑指offer(跳台阶)
题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果). 牛客网链接 思路 这一题和斐波那契数列思路完全一样. 假如青蛙从第n个 ...
- 剑指offer--39. 跳台阶
时间限制:1秒 空间限制:32768K 热度指数:375795 题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果). cla ...
- 剑指Offer-8.跳台阶(C++/Java)
题目: 一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果). 分析: 实际上就是斐波那契数列的一个应用,青蛙跳上n级台阶的跳法数等于跳 ...
- C#版 - 剑指offer 面试题9:斐波那契数列及其变形(跳台阶、矩形覆盖) 题解
面试题9:斐波那契数列及其变形(跳台阶.矩形覆盖) 提交网址: http://www.nowcoder.com/practice/c6c7742f5ba7442aada113136ddea0c3?tp ...
- 《剑指offer》 跳台阶
本题来自<剑指offer> 跳台阶 题目1: 一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果). 思路: 同上一篇. C ...
- 【Java】 剑指offer(9) 斐波那契数列及青蛙跳台阶问题
本文参考自<剑指offer>一书,代码采用Java语言. 更多:<剑指Offer>Java实现合集 题目 写一个函数,输入n,求斐波那契(Fibonacci)数列的第n项 ...
- 【剑指offer】09-2跳台阶,C++实现
原创博文,转载请注明出处! # 本文是牛客网<剑指offer>刷题笔记 1.题目 # 一只青蛙一次可以跳1级台阶,也可以跳2级.求该青蛙跳n级的台阶总共有多少种跳法. 2.思路 # 跳0级 ...
随机推荐
- iOS服务器证书不受信任的解决版本
参考文章链接: https://www.cnblogs.com/v-jing/p/6008964.html http://www.cocoachina.com/ios/20151021/13722.h ...
- three levels of abstraction
DATABASESYSTEM CONCEPTS SIXTH EDITION Abraham Silberschatz Yale University Henry F. KorthLehigh Univ ...
- Linux执行Cron Job失败,在Shell sh下执行却能成功 - 环境变量?
博客分类: Linux linuxcrontabpermissionetc/profile环境变量 一.我们常常碰到在shell下执行某个命令能够成功,比如执行一个java程序: java -jar ...
- maven配置(myeclipse版)
使用环境说明: OS:windows 7 64位 java version: "jdk1.8.0_66" IDE:myeclipse 2017 1.下载 下载地址:http://m ...
- 360电影主页和详情页爬去入Mysql库链表读取--lowbiprogrammer
import requests,os,jsonfrom lxml import etreefrom pymysql import *class Movie(object):def __init__(s ...
- Count the Colors---zoj1610线段树
题目链接 题意: 求每种颜色有几段线段: 模拟数组: #include<stdio.h> #include<iostream> #include<algorithm> ...
- 洛谷P3966 单词 [TJOI2013] AC自动机
正解:AC自动机 解题报告: 传送门! 先来提供一个40pts错解QAQ 首先看到这题就会想到AC自动机板子题2鸭!然后就照着那题的套路打一下,随便改一点儿,简单来说就是每次经过一个节点都要++,然后 ...
- 配合dedecms内容模型实现后台输入栏目id前端输出文章列表
为了简化开发的工作量,也方便编辑快速操作,决定将后台进行重新设置.配合dedecms内容模型实现后台输入栏目id前端输出文章列表,这样制作科室专题页也变快了很多.比如,我们添加一个“科室专家栏目id” ...
- notefirst使用
1:如果格式不正确,导入题录失败的话,可以手动添加.点击新建题录即可.输入文章的标题等信息. 2:导入word中的文献,可以使用word中notefirst的引文编辑功能,对文献进行删除,编辑等. 3 ...
- maven工程插件配置
<build> <!-- 该级工程会加载插件,放在父工程里 --> <plugins> <!-- 资源文件拷贝插件 --> <plugin> ...