31.最长定差子序列(medium)

1.题目链接:

1218. 最长定差子序列 - 力扣(LeetCode)1218. 最长定差子序列 - 给你一个整数数组 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]。 提示: * 1 <= arr.length <= 105 * -104 <= arr[i], difference <= 104https://leetcode.cn/problems/longest-arithmetic-subsequence-of-given-difference/description/

2.题目描述:

给你一个整数数组 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]。​
 ​
提示:
1 <= arr.length <= 10^5​
-10^4 <= arr[i], difference <= 10^4​

3. 解法(动态规划):
算法思路:
        这道题和 300. 最长递增子序列 有一些相似,但仔细读题就会发现,本题的 arr.lenght  高达            10^5 ,使用 O(N^2)  的 lcs  模型一定会超时。​
        那么,它有什么信息是 300. 最长递增子序列 的呢?是定差。之前,我们只知道要递增,不知道前                 一个数应当是多少;现在我们可以计算出前一个数是多少了,就可以用数值来定义 dp  数组的            值,并形成状态转移。这样,就把已有信息有效地利用了起来。

1. 状态表示:
          dp[i]  表示:以 i  位置的元素为结尾所有的子序列中,最长的等差子序列的长度。​

2. 状态转移方程:

对于 dp[i] ,上一个定差子序列的取值定为 arr[i] - difference 。只要找到以上一个数字为结尾的定差子序列长度的 dp[arr[i] - difference] ,然后加上 1 ,就是以 i  为结

尾的定差子序列的长度。

因此,这里可以选择使用哈希表做优化。我们可以把「元素,dp[j] 」绑定,放进哈希表中。甚至不用创建 dp  数组,直接在哈希表中做动态规划。​

3. 初始化:

刚开始的时候,需要把第一个元素放进哈希表中,hash[arr[0]] = 1

4. 填表顺序:

根据「状态转移方程」,填表顺序应该是「从左往右」。

5. 返回值:

根据「状态表示」,返回整个 dp  表中的最大值。​

Java算法代码

class Solution {
    public int longestSubsequence(int[] arr, int difference) {
        Map<Integer, Integer> hash = new HashMap<Integer, Integer>();

        int ret = 1;
        for(int a : arr){
            hash.put(a, hash.getOrDefault(a - difference, 0) + 1);
            ret = Math.max(ret,hash.get(a));
        }
        return ret;
    }
}

运行结果

动态规划

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值