zoukankan      html  css  js  c++  java
  • Leetcode 873 最长斐波那契子序列 记忆化递归与剪枝DP

      记忆化递归:

        int max = 0;
    
        public int lenLongestFibSubseq(int[] A) {
            int[][] cache = new int[A.length][A.length];
            for (int i = 0; i < A.length - 1; i++) {
                for (int j = i + 1; j < A.length; j++) {
                    lenLongestFibSubseqDP(A, i, j, cache);
                }
            }
            return max;
        }
    
        /**
         * @Author Niuxy
         * @Date 2020/6/28 10:08 下午
         * @Description 想要确定一个斐波那契数列,需要确定头两个元素
         * 因此要遍历数列中所有的两两组合,求出以其作为头元素和第二个元素的斐波那契额数列的长度,取最大值
         * G(f,s) 为以下标为 f,s 的元素为头元素与第二个元素的斐波那契数列长度
         */
        public int lenLongestFibSubseqDP(int[] A, int f, int s, int[][] cache) {
            if (s == A.length - 1) {
                return 2;
            }
            if (cache[f][s] != 0) {
                return cache[f][s];
            }
            int next = A[f] + A[s];
            for (int i = s + 1; i < A.length; i++) {
                if (A[i] != next) {
                    continue;
                }
                int re = lenLongestFibSubseqDP(A, s, i, cache) + 1;
                max = max > re ? max : re;
                cache[f][s] = re;
                return re;
            }
            cache[f][s] = 2;
            return 2;
        }

      转为递推即为 DP:

    /**
        * @Author Niuxy
        * @Date 2020/6/28 11:35 下午
        * @Description DP 解法,将递归转为递推
        */
        public int lenLongestFibSubseqDP2(int[] A){
            int[][] cache=new int[A.length][A.length];
            for(int i=0;i<A.length;i++){
                cache[A.length-1][i]=2;
            }
            for(int i=A.length-2;i>=0;i--){
                for(int j=i+1;j<A.length;j++){
                    if(cache[i][j]!=0){continue;}
                    int next=A[j]+A[i];
                    for(int k=j+1;k<A.length;k++){
                        if(A[k]==next){
                            int re = cache[j][k] + 1;
                            max = max > re ? max : re;
                            cache[i][j] = re;
                        }
                    }
                    cache[i][j]=cache[i][j]==0?2:cache[i][j];
                }
            }
            return max;
        }

      借助 hash 表剪枝:

     public int lenLongestFibSubseqDP2(int[] A) {
            int max = 0;
            int[][] cache = new int[A.length][A.length];
            Set<Integer> aSet = new HashSet<Integer>();
            for (int i = 0; i < A.length; i++) {
                cache[A.length - 1][i] = 2;
                aSet.add(A[i]);
            }
            for (int i = A.length - 2; i >= 0; i--) {
                for (int j = i + 1; j < A.length; j++) {
                    if (cache[i][j] != 0) {
                        continue;
                    }
                    int next = A[j] + A[i];
                    if (!aSet.contains(next)) {
                        cache[i][j] = 2;
                        continue;
                    }
                    for (int k = j + 1; k < A.length; k++) {
                        if (A[k] == next) {
                            int re = cache[j][k] + 1;
                            max = max > re ? max : re;
                            cache[i][j] = re;
                        }
                    }
                    cache[i][j] = cache[i][j] == 0 ? 2 : cache[i][j];
                }
            }
            return max;
        }

      基于剪枝及DP的思路,重写优化:

    public int lenLongestFibSubseq(int[] A) {
            int N = A.length;
            Set<Integer> S = new HashSet();
            for (int x: A) S.add(x);
            int ans = 0;
            for (int i = 0; i < N; i++)
                for (int j = i+1; j < N; j++) {
                    int x = A[j], y = A[i] + A[j];
                    int length = 2;
                    while (S.contains(y)) {
                        int tmp = y;
                        y += x;
                        x = tmp;
                        ans = Math.max(ans, ++length);
                    }
                }
            return ans >2 ? ans : 0;
        }

  • 相关阅读:
    线段树、最短路径、最小生成树、并查集、二分图匹配、最近公共祖先--C++模板
    数据结构中各种树
    你必须知道的基本位运算技巧(状压DP、搜索优化都会用到)
    memset为int型数组初始化问题
    Dev-C++添加代码格式化(format source code)工具Artistic Style
    让vs IIS Express支持本地静态Json文件
    什么是「供给侧改革」? 原标题:中央提的“供给侧改革”是啥意思?有谁能解说下吗?
    PowerDesigner用法和技巧
    php 调用 web Server(短信接口示例)
    sae相关配置
  • 原文地址:https://www.cnblogs.com/niuyourou/p/13205707.html
Copyright © 2011-2022 走看看