[leetcode 周赛 157] 1218 最长定差子序列
1218 Longest Arithmetic Subsequence of Given Difference 最长定差子序列
问题描述
给你一个整数数组 arr
和一个整数 difference
,请你找出 arr
中所有相邻元素之间的差等于给定 difference
的等差子序列,并返回其中最长的等差子序列的长度。
- 示例 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]。
- 提示:
1 <= arr.length <= 10^5
-10^4 <= arr[i], difference <= 10^4
思路
- 读题
顺序读取每个元素, 通过difference来筛选一个等差序列
动态规划
可以使用动态规划的思路, 建立两个函数:
- F(k) 前k个元素中最长定差子序列的长度
- G(num) 以元素num为定差子序列结尾的子序列长度
当前元素num
所在子序列长度等于前一个序列数num-difference
所在子序列的长度+1
G[num] = G[num-difference]+1
如果num
之前没有出现num-difference
元素 则G[num-difference]
为0
- 实例
arr
= [1,5,7,8,5,3,4,2,1],difference
= -2
步骤 | 已输入数 | 当前元素 | 最长定差子序列长度 |
---|---|---|---|
1 | 1 | G[1]=G[1-(-2)]+1=G[3]+1=0+1 =1 | F[1]=1 |
2 | 1 5 | G[5]=G[5-(-2)]+1=G[7]+1=0+1 =1 | F[2]=1 |
3 | 1 5 7 | G[7]=G[7-(-2)]+1=G[9]+1=0+1 =1 | F[3]=1 |
4 | 1 5 7 8 | G[8]=G[8-(-2)]+1=G[10]+1=0+1=1 | F[4]=1 |
5 | 1 5 7 8 5 | G[5]=G[5-(-2)]+1=G[7]+1=1+1 =2 | F[5]=1 |
6 | 1 5 7 8 5 3 | G[3]=G[3-(-2)]+1=G[5]+1=2+1 =3 | F[6]=1 |
7 | 1 5 7 8 5 3 4 | G[4]=G[4-(-2)]+1=G[6]+1=0+1 =1 | F[7]=1 |
8 | 1 5 7 8 5 3 4 2 | G[2]=G[2-(-2)]+1=G[4]+1=1+1 =2 | F[8]=1 |
9 | 1 5 7 8 5 3 4 2 1 | G[1]=G[1-(-2)]+1=G[3]+1=3+1 =4 | F[9]=1 |
- 图解
代码实现
动态规划
class Solution {
public int longestSubsequence(int[] arr, int difference) {
// res 输出结果 最长子序列长度
int res = 0;
// maps 存放键值出现时, 自己所在的定差子序列长度
Map<Integer, Integer> maps = new HashMap<>(arr.length);
// 相当于一个每次向右加+1的变长窗口
for (int a : arr) {
// 每个元素第一次出现时 初始值置为0
if (!maps.containsKey(a)) {
maps.put(a, 0);
}
// 该元素在子序列中前一个元素 可能出现的子序列长度(没有则为0)
int pre = maps.get(a-difference) == null ? 0 : maps.get(a-difference);
// 该元素子序列长度 比较自己所在序列以及前一个元素所在序列+1
int na = Math.max(maps.get(a), pre+1);
// 获取当前最大子序列长度
res = Math.max(na, res);
// 设置该元素所在子序列长度
maps.put(a, na);
//System.out.println(String.format("pre:%d na:%d res:%d maps:%s", pre, na, res, maps));
}
return res;
}
}
参考资源
第 157 场周赛 全球排名
【算法实况】体验使用 iPadOS 打算法竞赛 - 力扣周赛 - LeetCode Weekly 157