1218. 最长定差子序列

234 阅读2分钟

「这是我参与11月更文挑战的第4天,活动详情查看:2021最后一次更文挑战

题目

给你一个整数数组 arr 和一个整数 difference,请你找出并返回 arr 中最长等差子序列的长度,该子序列中相邻元素之间的差等于 difference 。

子序列 是指在不改变其余元素顺序的情况下,通过删除一些元素或不删除任何元素而从 arr 派生出来的序列。

输入: arr = [1,2,3,4], difference = 1
输出: 4
解释: 最长的等差子序列是 [1,2,3,4]
输入: arr = [1,3,5,7], difference = 1
输出: 1
解释: 最长的等差子序列是任意单个元素。

思路分析

本题最简单的方式自然也是枚举,但时间复杂度应该是指数级的了,并没有意义,不过我们发现,最长等差子序列其实就是第二长等差子序列加一个数。

需要理解的是,第二长等差子序列并不是只有一个,比如说最长等差子序列可能有1个,但是第二长等差子序列可能有5个。同时第二长等差子序列也未必一定是最长等差子序列的子集。

基于这个特点我们可以大胆猜测为一个动态规划的方法

 int longestSubsequence(vector<int>& arr, int difference) {
        int n = arr.size();
        int dp[n];
        for(int i = 0; i < n; i ++){
            dp[i] = 1;
        }
        for(int i = n - 2; i >= 0; i --){
            for(int j = i + 1; j < n; j ++){
                if(arr[i] + difference == arr[j]){
                    dp[i] = max(dp[j] + 1,dp[i]);
                }
            }   
        }
        for(int i = 0; i < n; i++){
            dp[0] = max(dp[0], dp[i]);
        }
        return dp[0];
    }

稍稍解释下这个代码,首先由于等差子序列最小为1,即元素本身,因此我们将dp数组初始化为1,然后从后往前不断遍历节点,第二层for循环遍历每个节点后面的节点,如果两个节点相差恰好为difference,则将dp[i] 与 dp[j] + 1做比较,选择最大值。

总结

这个方法可以正确运行,但是却会超时,这代表这个算法还是可以优化,下篇文章试试