「这是我参与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做比较,选择最大值。
总结
这个方法可以正确运行,但是却会超时,这代表这个算法还是可以优化,下篇文章试试