每日OJ题_子序列dp⑤_力扣1218. 最长定差子序列

目录

[力扣1218. 最长定差子序列](#力扣1218. 最长定差子序列)

解析代码


力扣1218. 最长定差子序列

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 <= 10^5
  • -10^4 <= arr[i], difference <= 10^4
cpp 复制代码
class Solution {
public:
    int longestSubsequence(vector<int>& arr, int difference) {

    }
};

解析代码

这道题和 力扣300. 最长递增子序列有⼀些相似,但仔细读题就会发现,本题的 arr.lenght 高达10^5 ,使用 O(N^2) 的 lcs 模型⼀定会超时。

那么它有什么信息是力扣300. 最长递增子序列的呢?是定差。之前只知道要递增,不知道前一个数应当是多少,现在我们可以计算出前一个数是多少了,就可以用数值来定义 dp 数组的值,并形成状态转移。这样,就把已有信息有效地利用了起来。

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

状态转移方程: 对于 dp[i] ,上一个定差子序列的取值定为 arr[i] - difference 。只要找到以上一个数字为结尾的定差子序列长度的 dp[arr[i] - difference] ,然后加上 1 ,就是以 i 为结尾的定差子序列的长度。 因此这里可以选择使用哈希表做优化。把元素和dp[j] 绑定,放进哈希表中。甚至不用创建 dp 数组,直接在哈希表中做动态规划。

初始化、填表顺序、返回值:

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

从左往右填表,最后返回dp表的最大值即可。

cpp 复制代码
class Solution {
public:
    int longestSubsequence(vector<int>& arr, int difference) {
        // dp[i] 表示:以 i 位置的元素为结尾所有的子序列中,最长的等差子序列的长度。
        int n = arr.size(), ret = 1;
        unordered_map<int, int> dpHash(n);
        dpHash[arr[0]] = 1;
        for(int i = 1; i < n; ++i)
        {
            // if(dpHash[arr[i] - difference]) // b存在
            //     dpHash[arr[i]] = dpHash[arr[i] - difference] + 1;
            // else
            //     dpHash[arr[i]] = 1;
            dpHash[arr[i]] = dpHash[arr[i] - difference] + 1; // 不存在就是0,直接加
            ret = max(ret, dpHash[arr[i]]);
        }
        return ret;
    }
};
相关推荐
南境十里·墨染春水6 小时前
C++传记(面向对象)虚析构函数 纯虚函数 抽象类 final、override关键字
开发语言·c++·笔记·算法
2301_797172756 小时前
基于C++的游戏引擎开发
开发语言·c++·算法
有为少年7 小时前
告别“唯语料论”:用合成抽象数据为大模型开智
人工智能·深度学习·神经网络·算法·机器学习·大模型·预训练
比昨天多敲两行7 小时前
C++ 二叉搜索树
开发语言·c++·算法
Season4507 小时前
C++11之正则表达式使用指南--[正则表达式介绍]|[regex的常用函数等介绍]
c++·算法·正则表达式
Tisfy8 小时前
LeetCode 2839.判断通过操作能否让字符串相等 I:if-else(两两判断)
算法·leetcode·字符串·题解
问好眼8 小时前
《算法竞赛进阶指南》0x04 二分-1.最佳牛围栏
数据结构·c++·算法·二分·信息学奥赛
海海不瞌睡(捏捏王子)8 小时前
C++ 知识点概要
开发语言·c++
会编程的土豆8 小时前
【数据结构与算法】优先队列
数据结构·算法
minji...10 小时前
Linux 进程信号(二)信号的保存,sigset_t,sigprocmask,sigpending
linux·运维·服务器·网络·数据结构·c++·算法