873. 最长的斐波那契子序列的长度

873. 最长的斐波那契子序列的长度【中等题】【每日一题】

思路:【动态规划】【官解注释】

定义二维dp数组,dp[j][i]表示以 arr[j]、arr[i]结尾的斐波那契子序列的长度,我们正序遍历数组,固定下标 i,然后从下标i-1开始,倒序遍历数组,固定下标 j,根据数组严格递增的性质进行剪枝,arr[j] * 2 < arr[i],当下标 j i 都固定好之后,我们判断数组中是否存在满足 arr[k] + arr[j] = arr[i] 的arr[k],并求出其下标k,如果不存在,则将k置为-1,通过将数组元素及其对应的下标丢入哈希map中来快速判断是否存在arr[k]

如果arr[k]存在,那么此时判断dp[k][j]的值,如果小于3,说明不存在以arr[k]、arr[j]结尾的斐波那契子序列,但由于此时 arr[k] + arr[j] = arr[i],所以dp[j][i] = 3 ;如果大于等于3 ,那么此时 dp[j][i] = dp[k][j] +1

整理可得 如果arr[k]存在,那么 dp[j][i] = Math.max(dp[k][j]+1,3);

每找到一个dp[j][i],就用它尝试去更新最大长度ans,保持ans是长度最大的斐波那契子序列。

代码:

class Solution {
    public int lenLongestFibSubseq(int[] arr) {
        int n = arr.length;
        if (n < 3){
            return 0;
        }
        //存储数组元素及其对应的下标
        Map<Integer,Integer> map = new HashMap<>();
        for (int i = 0; i < n; i++) {
            map.put(arr[i],i);
        }
        //定义dp数组,dp[j][i]表示 以 arr[j]、arr[i]作为最后两个数字的斐波那契子序列长度
        int[][] dp = new int[n][n];
        //定义ans变量来记录所有可能的斐波那契子序列的最长长度
        int ans = 0;
        //正序遍历数组,遍历到的下标i作为可能存在的斐波那契子序列的最后一个数字
        for (int i = 0; i < n; i++) {
            //确定下标i之后,从i-1开始反向遍历数组,遍历到的下标j作为可能存在的斐波那契子序列的倒数第二个数字
            //由于数组是严格单调递增的 且倒数第三个斐波那契子序列的假想数字 arr[k] 一定小于 arr[j] < arr[i]
            //即 arr[k] < arr[j] < arr[i]  =>  arr[j] > arr[i] /2   => arr[j] * 2 > arr[i]
            for (int j = i-1; j >= 0 && arr[j] * 2 > arr[i]; j--) {
                //确定好下标j之后,为了确保这是一个斐波那契子序列,则应保证 arr[k] + arr[j] = arr[i]
                //通过哈希map确认数组中是否存在满足上述等式的arr[k],如果存在,求出其数组下标k,即arr[k]在map中的value
                //如果不存在,则将k赋值为 -1
                int k = map.getOrDefault(arr[i]-arr[j],-1);
                //如果k>=0说明 k存在,对其dp[j][i]进行更新,否则说明 k不存在,对dp[j][i]不做处理
                if (k >= 0){
                    //由于存在arr[k]满足 arr[k] + arr[j] = arr[i],于是 dp[j][i]的值由 dp[k][j]决定
                    //转移方程为 dp[j][i] = dp[k][j]+1 , dp[k][j] >= 3
                    //                  = 3          ,dp[k][j] < 3 
                    //dp[k][j]小于3表示以arr[k]、arr[j]结尾的斐波那契数列不存在,于是 以 arr[j]、arr[i]结尾的斐波那契数列为起始序列 长度为3
                    dp[j][i] = Math.max(dp[k][j]+1,3);
                }
                //用当前的dp[j][i]去更新ans,保持ans是最大的斐波那契子序列
                ans = Math.max(ans,dp[j][i]);
            }
        }
        return ans;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值