动态规划之斐波那契数列问题

斐波那契数列问题(java语言)

斐波那契数列:指的是这样一个数列:0、1、1、2、3、5、8、13、21、34、……在数学上,斐波那契数列以如下被以递推的方法定义:F(0)=0,F(1)=1,F(n)=F(n-1)+F(n-2)(n ≥ 2,n ∈ N*)

package com.txw.javaCore.server.leetcode.dp;

import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;

/**
 * @PROJECT_NAME: DP
 * @DESCRIPTION: 动态规划解题套路框架
 * 1.动态规划问题的一般形式就是求最值
 * 2.求解动态规划的核心问题是穷举
 * 3.动态规划三要素:重叠子问题、最优子结构、状态转移方程
 * <p>
 * 思考:
 * 1.DP问题的base case(最简单情况)是什么?
 * 2.DP问题有什么“状态”?
 * 3.对于每个“状态”,可以做出什么“选择”使得“状态”发生改变?
 * 4.如何定义dp数组/函数的含义来表现“状态”和“选择”
 * <p>
 * 总结:状态、选择、dp数组的定义
 * @Author: wx:xiaoxuanwu_9703
 * @DATE: 2021/3/30 14:40
 */
@Slf4j
public class DpFrame {

    /**
     * 1.斐波那契数列-暴力递归
     *
     * @param num
     * @return
     */
    public static int blFib(int num) {
        if (0 == num) {
            return 0;
        }
        if (1 == num || 2 == num) {
            return 1;
        }
        return blFib(num - 1) + blFib(num - 2);
    }

    /**
     * 2.斐波那契数列-带备忘录的递归解法
     *
     * @param num
     * @return
     */
    public static int bwlFib(int num) {
        if (0 == num) {
            return 0;
        }
        //备忘录hashmap
        HashMap<Integer, Integer> memo = new HashMap<>();
        //将备忘录全部初始化为0
        for (int i = 0; i <= num; i++) {
            memo.put(i, 0);
        }
        //进行带备忘录的递归
        return helper(memo, num);
    }

    public static int helper(HashMap<Integer, Integer> memo, int num) {
        if (1 == num || 2 == num) {
            return 1;
        }
        //已经计算过了
        if (0 != memo.get(num)) {
            return memo.get(num);
        }
        memo.put(num, helper(memo, num - 1) + helper(memo, num - 2));
        return memo.get(num);
    }

    /**
     * 3.斐波那契数列-dp数组的迭代解法
     *
     * @param num
     * @return
     */
    public static int dpFib(int num) {
        if (0 == num) {
            return 0;
        }
        if (1 == num || 2 == num) {
            return 1;
        }
        /**DP table*/
        HashMap<Integer, Integer> dp = new HashMap<>(num + 1);
        //将备忘录全部初始化为0
        for (int i = 0; i <= num; i++) {
            dp.put(i, 0);
        }
        //base case
        dp.put(1, 1);
        dp.put(2, 1);
        for (int i = 3; i <= num; i++) {
            dp.put(i, dp.get(i - 1) + dp.get(i - 2));
        }
        return dp.get(num);
    }

    /**
     * 4.斐波那契数列-基于dp数组的迭代解法,将空间复杂度降为O(1)
     *
     * @param num
     * @return
     */
    public static int dpPreFib(int num) {
        if (0 == num) {
            return 0;
        }
        if (1 == num || 2 == num) {
            return 1;
        }
        //dp[n-2]
        int prev = 1;
        //dp[n-1]
        int curr = 1;
        for (int i = 3; i <= num; i++) {
            int sum = prev + curr;
            prev = curr;
            curr = sum;
        }
        return curr;

    }

    public static void main(String[] args) {
        log.info("--斐波那契数列-暴力递归:{}", blFib(6));
        log.info("--斐波那契数列-带备忘录的递归解法:{}", bwlFib(7));
        log.info("--斐波那契数列-dp数组的迭代解法:{}", dpFib(8));
        log.info("--斐波那契数列-基于dp数组的迭代解法,将空间复杂度降为O(1):{}", dpPreFib(9));
    }

}

运行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值