斐波那契 三种不同算法

首先这是传统递归

   // 传统方法
    public Long fib(int n) {
    
    
        if (n == 0) {
    
    
            return 0L;
        } else if (n == 1 || n == 2) {
    
    
            return 1L;
        } else {
    
    
            return fib(n - 1) + fib(n - 2);
        }
    }

备忘录算法 这里用的是map字典

    // 备忘录
    public Long backupFib(int n) {
    
    
        if (n < 1) {
    
    
            return 0L;
        }
        // 列,列项和
        Map<Integer, Long> map = new HashMap<>(16);
        return this.helper(map,n);
    }

    public Long helper(Map<Integer, Long> map, int n) {
    
    
        if (n == 1 || n == 2) {
    
    
            return 1L;
        }
        if (map.containsKey(n)) {
    
    
            return map.get(n);
        }
        map.put(n,helper(map,n-1)+helper(map,n-2));
        return map.get(n);
    }

dp数组迭代解法

  // dp数组迭代
    public Long dpFib(int n) {
    
    
        Long[] dp = new Long[]{
    
    };
        dp[0] = 0L;
        dp[1] = dp[2] = 1L;

        for (int i = 3; i <= n ; i++) {
    
    
            dp[i] = dp[i-1] + dp[i-2];

        }
        return dp[n];
    }


    // dp优化
    public Long dpUpFib(int n) {
    
    
        if (n == 0) {
    
    
            return 0L;
        } else if (n == 1 || n == 2) {
    
    
            return 1L;
        }
        Long prev = 1L;
        Long curr = 1L;

        for (int i = 3; i <= n ; i++) {
    
    

            Long sum = prev+curr;
            prev = curr;
            curr = sum;

        }
        return curr;
    }
可以看到 在40项的时候 传统递归劣势已经体现,而在45项往后 传统递归会几乎指数型降低 非常慢!(不做截图展示)

在这里插入图片描述

当项数到达一千时 (传统递归已经完全不适用 注释掉)可以看到两者效率都很高 dp略大于map

在这里插入图片描述

解法思路:

1、递归没什么好说的 又让人头大 效率又低
2、备忘录算法: 把n项的下标当成map的key 把n项值当成map的value ,
例如数列:1、1、2、3、5 、8。。。。 第4项 map的key就是4 ,value是 3 ,第5项key value都是5
计算第6项时,我们只需将key为 4 和key 为5 两项的value相加即可
3、dp算法: 和备忘录很相似 只不过备忘录是⾃顶向下 就是说 计算第6项 是去找第4,5项,而dp则是⾃底向上,
这个 自底向上
自底向下 可能不是很好理解,两种算法乍一看也差不多 但是看到dp优化的时候 就会比较明朗

猜你喜欢

转载自blog.csdn.net/qq_36268103/article/details/118213014
今日推荐