[剑之offer] 10 斐波那契数列

一、问题

1、写一个函数,输入 n ,求斐波那契(Fibonacci)数列的第 n 项。斐波那契数列的定义如下

F(0) = 0, F(1) = 1

F(N) = F(N - 1) + F(N - 2), 其中 N > 1.

斐波那契数列由 0 和 1 开始,之后的斐波那契数就是由之前的两数相加而得出。

2、示例

输入:n = 2
输出:1

输入:n = 5
输出:5

二、解题方法

解题思路:
斐波那契数列的定义是 f(n + 1) = f(n) + f(n - 1)f(n+1)=f(n)+f(n−1) ,生成第 nn 项的做法有以下几种:

1、递归法:

原理: 把 f(n)f(n) 问题的计算拆分成 f(n-1)f(n−1) 和 f(n-2)f(n−2) 两个子问题的计算,并递归,以 f(0)f(0) 和 f(1)f(1) 为终止条件。

缺点: 大量重复的递归计算,例如 f(n)f(n) 和 f(n - 1)f(n−1) 两者向下递归需要 各自计算 f(n - 2)f(n−2) 的值。

2、记忆化递归法:

原理: 在递归法的基础上,新建一个长度为 nn 的数组,用于在递归时存储 f(0)f(0) 至 f(n)f(n) 的数字值,重复遇到某数字则直接从数组取用,避免了重复的递归计算。

缺点: 记忆化存储需要使用 O(N)O(N) 的额外空间。

3、动态规划:

原理: 以斐波那契数列性质 f(n + 1) = f(n) + f(n - 1)f(n+1)=f(n)+f(n−1) 为转移方程。
从计算效率、空间复杂度上看,动态规划是本题的最佳解法。

package com.haoxiansheng.demo01.SwordfingerOffer;

import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;

/**
 * @author flame
 * @data 2020/10/22
 */
@Slf4j
public class FibDemo {
    
    
    public static void main(String[] args) {
    
    
        log.info("fib=>{}", fib(2000));
    }
    // 为什么选1000000007
    //理由大概是“int32类型是十位数,对1e9取模可防止int32溢出”、“1e9+7是质数,
    //对质数取模可以尽可能地让模数避免相等”以及“1e9+7是离1e9最近的质数,比较好记”
    public static int fib(int n) {
    
    
        int a =0;
        int b = 1;
        int sum;
        for (int i =0 ; i< n; i++) {
    
    
            sum = (a + b) % 1000000007;
            a = b;
            b = sum;
        }

        return a;
    }

    int constant = 1000000007;

    public int fib1(int n) {
    
    
        if (n < 2)
            return n;
        int first = fib(n - 1) % constant;
        int second = fib(n - 2) % constant;
        return (first + second) % constant;
    }

    public int fib2(int n) {
    
    
        return fib(n, new HashMap<>());
    }

    public int fib(int n, Map<Integer, Integer> map) {
    
    
        if (n < 2)
            return n;
        if (map.containsKey(n))
            return map.get(n);
        int first = fib(n - 1, map) % constant;
        map.put(n - 1, first);
        int second = fib(n - 2, map) % constant;
        map.put(n - 2, second);
        int res = (first + second) % constant;
        map.put(n, res);
        return res;
    }

    // 非递归解决
    public int fib3(int n) {
    
    
        int constant = 1000000007;
        int first = 0;
        int second = 1;
        while (n-- > 0) {
    
    
            int temp = first + second;
            first = second % constant;
            second = temp % constant;
        }
        return first;
    }


}

1000000007 需要研究一下。计算需要画流程区理解

猜你喜欢

转载自blog.csdn.net/qq_40996741/article/details/109233378