剑指offer 面试题10斐波那契数列

斐波那契数列
以及青蛙跳台阶问题

package com.cloud.algorithm.demo;

import org.junit.Test;

/**
 * DATE: 2021/3/31
 * Author: xiaoqu
 * Version: 1.0.0
 * 斐波那契数列
 */
public class Topic10 {

    /**
     * 面试题10: 菲波那切数列
     * 题目一:求斐波那契数列数列的第n项
     * 写一个函数,输入n 求斐波那契(Fibonacci)数列的第n项。菲波那切数列的定义如下
     * 		 {0               n=0
     * f(n)= {1               n=1
     * 		 {f(n-1)+f(n-2)   n>1
     */
    @Test
    public void topic10_1() {
        //递归
        long i = System.currentTimeMillis();
        long data = this.demo01(8);
        long j = System.currentTimeMillis();
        System.out.println("递归结果为:" + data + ",使用时间为:" + (j - i));

        //循环
        long i1 = System.currentTimeMillis();
        long data1 = this.demo02(8);
        long j1 = System.currentTimeMillis();
        System.out.println("循环结果为:" + data1 + ",使用时间为:" + (j1 - i1));

        /**
         * 当n=50
         * 递归结果为:12586269025,使用时间为:76074
         * 循环结果为:12586269025,使用时间为:0
         * 从结果可以看出递归慢很多,主要是递归里面很多计算都是重复的
         */

    }

    /**
     * 题目二:青蛙跳台阶问题
     * 一只青蛙一次可以调一级台阶,也可以跳2级台阶,
     * 求该青蛙跳上一个n级的台阶总共有多少种跳法
     */
    @Test
    public void topic10_2() {
        /**
         * 如果n=1  结果为1
         * 如果n=2 结果为2
         * 如果为n (n>2) 第一步有两种,要么第一步跳一下,要么跳两下,
         * 如果第一步跳一下,则剩下的台阶为 n-1
         * 如果第一步跳两下,则剩下的台阶为n-2
         * 依次类推 f(n)=f(n-1)+f(n-2)
         */
        //递归
        long i = System.currentTimeMillis();
        long data = this.demo03(40);
        long j = System.currentTimeMillis();
        System.out.println("递归结果为:" + data + ",使用时间为:" + (j - i));

        //循环
        long i1 = System.currentTimeMillis();
        long data1 = this.demo04(40);
        long j1 = System.currentTimeMillis();
        System.out.println("循环结果为:" + data1 + ",使用时间为:" + (j1 - i1));

        /**
         * 递归结果为:165580141,使用时间为:421
         * 循环结果为:165580141,使用时间为:0
         */

    }

    /**
     * 题目3:青蛙跳台阶变形版
     * 青蛙一次可以跳上1级台阶,也可以跳2级,。。。。也可以跳n级
     * 此时跳上一个n级台阶总共有多少跳法
     */
    @Test
    public void topic10_3() {
        /**
         * 青蛙如果第一步跳一级台阶  剩下的台阶跳法就是f(n-1)
         * 青蛙如果第一步跳二级台阶  剩下的台阶跳法就是f(n-2)
         * 。。。。。
         * 青蛙如果第一步跳n-1级台阶  剩下的台阶跳法就是f(1)
         * 青蛙如果第一步跳n级台阶  剩下的台阶跳法就是f(0)
         * 即总跳法为 f(n)=f(n-1)+f(n-2)+......+f(1)+f(0)
         * 变形为
         * f(n-1)=f(n-2)+f(n-3)+......+f(1)+f(0)
         * 两者相减得如下
         * f(n)-f(n-1)=f(n-1)
         * f(n)=2f(n-1)
         * 2f(n-1)=2x2f(n-2)
         * f(n)=2x2f(n-2)
         * 推论得出
         * f(n)=2^(n-1) f(n)=2^(n-1)
         * 即实际求的是
         *
         * f(n)=2^(n-1)
         */
        long l = this.demo05(3);
        System.out.println(l);

    }

    /**
     * 口            口口口口口口口口
     * 口            口口口口口口口口
     * <p>
     * 我们可以用2X1的小矩形横着或者竖着去覆盖更大的矩形,
     * 请问用8个2X1的小矩形无重叠地覆盖在一个2X8的大矩形
     * 总共有多少种方法
     */
    @Test
    public void topic10_4() {

        /**
         * 如果第一个横着放 则右边剩余6个 为 f(6)
         * 如果第一个竖着放 则右边剩余7个 为 f(7)
         * 则总次数为 f(8)=f(6)+f(7) 解法依旧为斐波那契数列
         */
    }


    /**
     * 递归
     *
     * @return
     */
    public long demo01(long n) {
        if (n == 0) {
            return 0;
        } else if (n == 1) {
            return 1;
        } else {
            return demo01(n - 1) + demo01(n - 2);
        }
    }

    /**
     * 时间复杂度为O(n)
     *
     * @param n
     * @return
     */
    public long demo02(long n) {
        if (n == 0) {
            return 0;
        } else if (n == 1) {
            return 1;
        } else {
            long k1 = 0;
            long k2 = 1;
            long kn = 0;
            for (int i = 2; i <= n; i++) {
                kn = k1 + k2;
                k1 = k2;
                k2 = kn;
            }
            return kn;
        }
    }

    /**
     * 递归
     *
     * @param n
     * @return
     */
    public long demo03(long n) {

        if (n == 1) {
            return 1;
        } else if (n == 2) {
            return 2;
        } else {
            return demo03(n - 1) + demo03(n - 2);
        }
    }

    /**
     * 循环
     *
     * @return
     */
    public long demo04(long n) {
        if (n == 1) {
            return 1;
        } else if (n == 2) {
            return 2;
        } else {
            long kn = 0;
            long kn1 = 1;
            long kn2 = 2;
            for (int i = 3; i <= n; i++) {
                kn = kn1 + kn2;
                kn1 = kn2;
                kn2 = kn;
            }
            return kn;
        }
    }

    /**
     * 2^(n-1)
     *
     * @return
     */
    public long demo05(long n) {
        int j = 1;
        for (int i = 1; i < n; i++) {
            j = 2 * j;
        }
        return j;
    }

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值