# 1218. 最长定差子序列 ## 题目地址(1218. 最长定差子序列) <https://leetcode-cn.com/problems/longest-arithmetic-subsequence-of-given-difference/> ## 题目描述 ``` <pre class="calibre18">``` 给你一个整数数组 arr 和一个整数 difference,请你找出 arr 中所有相邻元素之间的差等于给定 difference 的等差子序列,并返回其中最长的等差子序列的长度。 示例 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 ``` ``` ## 前置知识 - 数组 - 动态规划 ## 公司 - 腾讯 ## 思路 最直观的思路是双层循环,我们暴力的枚举出以每一个元素为开始元素,以最后元素结尾的的所有情况。很明显这是所有的情况,这就是暴力法的精髓, 很明显这种解法会 TLE(超时),不过我们先来看一下代码,顺着这个思维继续思考。 ### 暴力法 ``` <pre class="calibre18">``` <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">longestSubsequence</span><span class="hljs-params">(self, arr: List[int], difference: int)</span> -> int:</span> n = len(arr) res = <span class="hljs-params">1</span> <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(n): count = <span class="hljs-params">1</span> <span class="hljs-keyword">for</span> j <span class="hljs-keyword">in</span> range(i + <span class="hljs-params">1</span>, n): <span class="hljs-keyword">if</span> arr[i] + difference * count == arr[j]: count += <span class="hljs-params">1</span> <span class="hljs-keyword">if</span> count > res: res = count <span class="hljs-keyword">return</span> res ``` ``` **复杂度分析** - 时间复杂度:O(N2)O(N^2)O(N2) - 空间复杂度:O(N)O(N)O(N) ### 动态规划 上面的时间复杂度是 O(n^2), 有没有办法降低到 O(n)呢?很容易想到的是空间换时间的解决方案。 我的想法是将`以每一个元素结尾的最长等差子序列的长度`统统存起来,即`dp[num] = maxLen` 这样我们遍历到一个新的元素的时候,就去之前的存储中去找`dp[num - difference]`, 如果找到了,就更新当前的`dp[num] = dp[num - difference] + 1`, 否则就是不进行操作(还是默认值 1)。 这种空间换时间的做法的时间和空间复杂度都是 O(n)。 ## 关键点解析 - 将`以每一个元素结尾的最长等差子序列的长度`统统存起来 ## 代码 ``` <pre class="calibre18">``` <span class="hljs-title">#</span> <span class="hljs-title"># @lc app=leetcode.cn id=1218 lang=python3</span> <span class="hljs-title">#</span> <span class="hljs-title"># [1218] 最长定差子序列</span> <span class="hljs-title">#</span> <span class="hljs-title"># @lc code=start</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solution</span>:</span> <span class="hljs-title"># 动态规划</span> <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">longestSubsequence</span><span class="hljs-params">(self, arr: List[int], difference: int)</span> -> int:</span> n = len(arr) res = <span class="hljs-params">1</span> dp = {} <span class="hljs-keyword">for</span> num <span class="hljs-keyword">in</span> arr: dp[num] = <span class="hljs-params">1</span> <span class="hljs-keyword">if</span> num - difference <span class="hljs-keyword">in</span> dp: dp[num] = dp[num - difference] + <span class="hljs-params">1</span> <span class="hljs-keyword">return</span> max(dp.values()) <span class="hljs-title"># @lc code=end</span> ``` ``` **复杂度分析** - 时间复杂度:O(N)O(N)O(N) - 空间复杂度:O(N)O(N)O(N) 大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:<https://github.com/azl397985856/leetcode> 。 目前已经 37K star 啦。 大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。 ![](https://img.kancloud.cn/cf/0f/cf0fc0dd21e94b443dd8bca6cc15b34b_900x500.jpg)