【动态规划】——斐波那契数列

本文详细解析动态规划的步骤,包括确定base case、状态定义、行为选择与状态转移方程,以及从暴力递归到备忘录法、数组dp和优化算法的应用,以斐波那契数列为例进行深入讲解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

动态规划

如何列出正确的状态转移方程:

  1. 确定base case
  2. 确定“状态",也就是原问题和子问题中的变量
  3. 确定选择,也就是导致“状态”产生变化的行为
  4. 明确 dp 函数 / 数组的定义

动态规划的暴力求解阶段就是回溯法。只有有的问题可以通过巧妙的定义,构造出最优子结构,找出重复子问题,可以用DP table或者“备忘录”优化,将递归树大幅剪枝,这就是动态规划的解法。——先找出动态转移方程,再穷举“状态”

回溯法,就是穷举。

斐波那契数列

  1. 暴力递归

    int fib(int N){
    	if(N == 0) return 0;
    	if(N == 1 || N == 2) return 1;
    	return fib(N - 1) + fib(N - 2);
    }
    

    时间复杂度O(2^n)

  2. 带备忘录的递归解法——自顶向下

    每次算出某个子问题的答案后别返回,先将其记到"备忘录"里再返回;每次遇到一个子问题先去备忘录里查

    • 使用数组当“备忘录”
    • 哈希表(字典)
    Integer[] memo;
    public int fib(int n) {
        memo = new Integer[n+1];
        return recursive(n);
    }   
    private int recursive(int num){
        if(memo[num]!=null) return memo[num];
        if(num==0) return 0;
        if(num==1) return 1;
        return memo[num] = ( fib(num-1)+fib(num-2));
    }
    
  3. dp数组的迭代解法——自底向下

    public int fib(int n) {
        if(n == 0) return 0;
        if(n == 1 || n == 2) return 1;
        int[] f= new int[n+1];
        f[0] = 0;
        f[1]= 1;
        for(int i = 2;i<=n;i++) 
            f[i] =f[i-1]+f[i-2];
        return f[n];
    }
    

  4. 优化DP表,两个状态

    int fin(int N){
        if(N == 0) return 0;
        if(N == 2 || N == 1) return 1;
        int prev = 1,curr = 1;
        for(int i = 3;i <= N;i++){
            int sum = prev + curr;
            prev = curr;
            curr = sum;
        }
        return curr;
    }
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值