个人主页:元清加油_【C++】,【C语言】,【数据结构与算法】-CSDN博客
个人专栏
力扣递归题
【C++】
http://t.csdnimg.cn/6AbpV
数据结构
前言:这个专栏主要讲述动态规划算法,所以下面题目主要也是这些算法做的
我讲述题目会把讲解部分分为3个部分:
1、题目解析
2、算法原理思路讲解
3、代码实现
最长定差子序列
题目链接:最长定差子序列
题目
给你一个整数数组 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 <= 104
解法
算法原理解析
我们这题使用动态规划,我们做这类题目可以分为以下五个步骤
- 状态显示
- 状态转移方程
- 初始化(防止填表时不越界)
- 填表顺序
- 返回值
这道题和
有⼀些相似,但仔细读题就会发现,本题的
arr.lenght
⾼达 10^5 ,使⽤
O(N^2)
的
lcs
模型⼀定会超时。
- 状态显示
dp[i] 表⽰:以 i 位置的元素为结尾所有的⼦序列中,最⻓的等差⼦序列的⻓度。
- 状态转移方程
对于
dp[i]
,上⼀个定差⼦序列的取值定为
arr[i] - difference
。只要找到以上⼀个数 字为结尾的定差⼦序列⻓度的 dp[arr[i] - difference]
,然后加上
1
,就是以
i
为结尾的定差⼦序列的⻓度。 因此,这⾥可以选择使⽤哈希表做优化。我们可以把「元素, dp[j]
」绑定,放进哈希表中。甚⾄不⽤创建 dp
数组,直接在哈希表中做动态规划。
- 初始化(防止填表时不越界)
刚开始的时候,需要把第⼀个元素放进哈希表中,
hash[arr[0]] = 1。
- 填表顺序
根据「状态转移⽅程」,填表顺序应该是「从左往右」.
- 返回值
根据「状态表⽰」,返回整个
dp
表中的最⼤值.
代码实现
class Solution {
public:
int longestSubsequence(vector<int>& arr, int difference)
{
unordered_map<int, int> hash; // {arr[i], dp[i]}
hash[arr[0]] = 1; // 初始化
int ret = 1;
for(int i = 1; i < arr.size(); i++)
{
hash[arr[i]] = hash[arr[i] - difference] + 1;
ret = max(ret, hash[arr[i]]);
}
return ret;
}
};