子序列——换个马甲LIS(三)

2018-11-09  本文已影响0人  旺叔叔

LeetCode_873_LengthofLongestFibonacciSubsequence

题目分析:

本质还是LIS,只是不能二分优化了。回忆这三个题走来。
1.求上升。
2.上升条件变了。
3.不是上升了。--- 虽然结果数字是上升,但是之前维护的那个数组已经无效了。
dp[i][j] (i < j) 代表包含i和j下标的子序列最大长度。
倒着遍历,如果A[i] + A[j]存在,长度 + 1,否则长度默认是2;
用一个max收集最大长度。
if(map.containsKey(A[i] + A[j])){
      int position = map.get(A[i] + A[j]);
      dp[i][j] = dp[j][position] + 1;
}else {
      dp[i][j] = 2;
}
计算过程中我们需要反复查询某个“值”是否在数组中,数组只能根据下标快速查询。
所以我们用一个map,来把只能下标查询的数组,变成可以值查询的map。
一点点数据结构的感觉?蛤?数据结构本质就是方便特定情况的CRUD。

解法一:直接dp

public static int lenLongestFibSubseq(int[] A) {
    int max = 0;
    Map<Integer,Integer> map = new HashMap<>();

    for(int i = 0; i < A.length; i++)
        map.put(A[i], i);
    int [][]dp = new int[A.length][A.length];

    for(int i = A.length - 1; i >= 0; i--){
        for(int j = i + 1; j < A.length; j++){
            if(map.containsKey(A[i] + A[j])){
                int position = map.get(A[i] + A[j]);
                dp[i][j] = dp[j][position] + 1;
                max = Math.max(max,dp[i][j]);
            }else {
                dp[i][j] = 2;
            }
        }
    }

    return max;
}

解法二:暴力

/**
 * 直接暴力效率也不差
 */
public static int lenLongestFibSubseq(int[] A) {
    int max = 0;
    Set<Integer> set = new HashSet<>();
    for (int a : A)
        set.add(a);
    for (int i = 0; i < A.length; ++i)
        for (int j = i + 1; j < A.length; ++j) {
            int x = A[j], y = A[i] + A[j];
            int length = 2;
            while (set.contains(y)) {
                int z = x + y;
                x = y;
                y = z;
                max = Math.max(max, ++length);
            }
        }

    return max >= 3 ? max : 0;
}
上一篇下一篇

猜你喜欢

热点阅读