当前位置: 代码迷 >> 综合 >> 【动归】B014_Longest Arithmetic Subsequence of Given Differences(dp)
  详细解决方案

【动归】B014_Longest Arithmetic Subsequence of Given Differences(dp)

热度:92   发布时间:2024-01-27 05:50:17.0

一、题目描述

Given an integer array arr and an integer difference, 
return the length of the longest subsequence in arr 
which is an arithmetic sequence such that the difference 
between adjacent elements in the subsequence equals difference.Input: arr = [1,3,5,7], difference = 1
Output: 1
Explanation: The longest arithmetic subsequence is any single element.

二、题解

方法一:直接 dp

  • 定义状态
    • d p [ i ] dp[i] 表示区间 [ 0 , i ] [0, i] 的最长等差子序列。
  • 思考状态转移方程
    • 满足 d p [ i ] ? d p [ j ] = d i f f dp[i] - dp[j] = diff 时, d p [ i ] = m a x ( d p [ i ] , d p [ j ] + 1 ) dp[i] = max(dp[i], dp[j] + 1)
  • 思考初始化
    • d p [ 0... i ] = 1 dp[0...i] = 1
  • 思考输出 d p [ N ? 1 ] dp[N-1]

你有没有考虑到数组 arr 中存在负数?比如: [ 3 , 4 , ? 3 , ? 2 , ? 4 ] [3, 4,-3,-2,-4] d i f f = ? 5 diff = -5 时,答案应该是 2 即子序列 [3, -2]。而依照上面的算法根本算不出 2,把条件判断改为:

  • if (arr[i] - arr[j] == difference || arr[j] - arr[i] == difference) 怎么样? 3 ? ( ? 2 ) = = 5 3 - (-2) == 5 ,看来也不行。
public int longestSubsequence(int[] arr, int difference) {int N = arr.length;int[] dp = new int[N];Arrays.fill(dp, 1);for (int i = 1; i < N; i++)for (int j = 0; j < i; j++) {if (arr[i] - arr[j] == difference)dp[i] = Math.max(dp[i], dp[j] + 1);}return dp[N-1];
}

复杂度分析

  • 时间复杂度: O ( N 2 ) O(N^2)
  • 空间复杂度: O ( N ) O(N)

方法二:map

使用映射表存储等差数列的元素无需考虑子结构的顺序性,拿出一个数 n,直接查找它的等差数:

  • 如果查找到,则以 n 结尾的最长等差子序列长度 +1;
  • 如果没找到,则以 n 结尾的最长等差子序列长度还是 1。
  • 状态转移不难想到: m a p [ n ] = m a p [ n ? d i f f ] + 1 map[n] = map[n-diff] + 1
public int longestSubsequence(int[] arr, int difference) {HashMap<Integer, Integer> dp = new HashMap<>();int LS = 0;for (int n : arr) {dp.put(n, dp.getOrDefault(n-difference, 0) + 1);LS = Math.max(LS, dp.get(n));}return LS;
}

复杂度分析

  • 时间复杂度: O ( N ) O(N)
  • 空间复杂度: O ( N ) O(N)
  相关解决方案