问题:最长定差子序列
给你一个整数数组 arr 和一个整数 difference,请你找出并返回 arr 中最长等差子序列的长度,该子序列中相邻元素之间的差等于 difference 。
子序列 是指在不改变其余元素顺序的情况下,通过删除一些元素或不删除任何元素而从 arr 派生出来的序列。
示例 1:
输入:arr = [1,2,3,4], difference = 1
输出:4
解释:最长的等差子序列是 [1,2,3,4]。
示例 2:
输入:arr = [1,3,5,7], difference = 1
输出:1
解释:最长的等差子序列是任意单个元素。
示例 3:
输入:arr = [1,5,7,8,5,3,4,2,1], difference = -2
输出:4
解释:最长的等差子序列是[7,5,3,1]。
思路一:动态规划
动态规划有几个典型特征,最优子结构、状态转移方程、边界、重叠子问题。
在最长定差子序列问题中:
假设
d
p
[
i
]
dp[i]
dp[i]为以
a
r
r
[
i
]
arr[i]
arr[i]为结尾的最长等差子序列的长度,因此我们可以在
a
r
r
[
i
]
arr[i]
arr[i]左侧找到满足
a
r
r
[
j
]
=
a
r
r
[
i
]
−
d
arr[j]=arr[i]-d
arr[j]=arr[i]−d,则此时
d
p
[
i
]
=
d
p
[
j
]
+
1
dp[i]=dp[j]+1
dp[i]=dp[j]+1,其中
0
<
j
<
i
0<j<i
0<j<i。
因此从数组元素自左向右遍历的过程中:
- 最优子结构为: d p [ j ] + 1 dp[j]+1 dp[j]+1
- 状态转移方程为: d p [ i ] = d p [ j ] + 1 → d p [ i ] = d p [ i − d ] + 1 dp[i]=dp[j]+1 \rightarrow dp[i]=dp[i-d]+1 dp[i]=dp[j]+1→dp[i]=dp[i−d]+1
- 边界为: d p [ 1 ] = 1 dp[1]=1 dp[1]=1
- **重叠问题:**等差子序列长度计算问题
- 最终答案: m a x ( d p [ i ] , d p [ j ] ) max(dp[i],dp[j]) max(dp[i],dp[j])
代码如下:
class Solution {
public int longestSubsequence(int[] arr, int difference) {
int result = 0;
Map<Integer,Integer> map = new HashMap<>();
for(int i : arr){
map.put(i,map.getOrDefault(i-difference,0)+1);
result = Math.max(result,map.get(i));
}
return result;
}
}