这是我参与11月更文挑战的第8天,活动详情查看:2021最后一次更文挑战
最长定差子序列
该题出自力扣的1218题——最长定差子序列(中等题),题解是自己做的
审题
给你一个整数数组 arr 和一个整数 difference,请你找出并返回 arr 中最长等差子序列的长度,该子序列中相邻元素之间的差等于 difference 。
子序列 是指在不改变其余元素顺序的情况下,通过删除一些元素或不删除任何元素而从 arr 派生出来的序列。
-
简单概括就是,等差序列,找出数组内最长长度的等差序列,并返回长度
-
方法的本质就是找到一个数为基准,并且遍历循环,找到与他相关的等差序列并返回最长长度
-
(×)方法一:双重循环
-
因为,没有等差序列的话,最小的就是本身,所以定义了一个变量存储长度,初值为1
-
for循环外层整个数组,定义每次的局部变量作为每一个遍历的最长长度
-
内层循环(双指针),if 判断是否等差序列,是的话,直接跳转到相应的序列;最后比较当前等差序列长度,取最大值
public static int longestSubsequence(int[] arr, int difference) { int result = 1; for (int i = 0; i < arr.length; i++) { int num = 1; int q = i; for (int j =i+1;j<arr.length;j++){ if (arr[j] - arr[q] == difference){ num++; q = j; continue; } } result = Math.max(result,num); } return result; } -
时间复杂度O(n²),空间复杂度O(1),最终被巨型测试用例劝退,超时了
-
-
(√)方法二:利用HashMap
- 其实原理就是找到等差序列的初值,利用HashMap对数组的每一个元素都存储当前的值和等差前的值、
- 假如被等差的值不存在就存储1
- 最终赋值即可
- 可以理解成动态规划,对每一次获取到的元素进行存值;时间复杂度O(n),是遍历数组的for循环;空间复杂度是O(n),是定义一个HashMap
编码
public static int longestSubsequence1(int[] arr, int difference) {
HashMap<Integer,Integer> map = new HashMap<>(arr.length);
int res = 0;
for (int num : arr){
map.put(num,map.getOrDefault(num - difference,0)+1);
res = Math.max(res,map.get(num));
}
return res;
}