第五章 - 高频考题(中等)
1906. 查询差绝对值的最小值
1218. 最长定差子序列

题目地址(1218. 最长定差子序列)

题目描述

1
给你一个整数数组 arr 和一个整数 difference,请你找出 arr 中所有相邻元素之间的差等于给定 difference 的等差子序列,并返回其中最长的等差子序列的长度。
2
3
4
5
示例 1:
6
7
输入:arr = [1,2,3,4], difference = 1
8
输出:4
9
解释:最长的等差子序列是 [1,2,3,4]。
10
示例 2:
11
12
输入:arr = [1,3,5,7], difference = 1
13
输出:1
14
解释:最长的等差子序列是任意单个元素。
15
示例 3:
16
17
输入:arr = [1,5,7,8,5,3,4,2,1], difference = -2
18
输出:4
19
解释:最长的等差子序列是 [7,5,3,1]。
20
21
22
提示:
23
24
1 <= arr.length <= 10^5
25
-10^4 <= arr[i], difference <= 10^4
Copied!

前置知识

  • 数组
  • 动态规划

公司

  • 腾讯

思路

最直观的思路是双层循环,我们暴力的枚举出以每一个元素为开始元素,以最后元素结尾的的所有情况。很明显这是所有的情况,这就是暴力法的精髓, 很明显这种解法会 TLE(超时),不过我们先来看一下代码,顺着这个思维继续思考。

暴力法

1
def longestSubsequence(self, arr: List[int], difference: int) -> int:
2
n = len(arr)
3
res = 1
4
for i in range(n):
5
count = 1
6
for j in range(i + 1, n):
7
if arr[i] + difference * count == arr[j]:
8
count += 1
9
10
if count > res:
11
res = count
12
13
return res
Copied!
复杂度分析
  • 时间复杂度:$O(N^2)$
  • 空间复杂度:$O(N)$

动态规划

上面的时间复杂度是 O(n^2), 有没有办法降低到 O(n)呢?很容易想到的是空间换时间的解决方案。
我的想法是将以每一个元素结尾的最长等差子序列的长度统统存起来,即dp[num] = maxLen 这样我们遍历到一个新的元素的时候,就去之前的存储中去找dp[num - difference], 如果找到了,就更新当前的dp[num] = dp[num - difference] + 1, 否则就是不进行操作(还是默认值 1)。
这种空间换时间的做法的时间和空间复杂度都是 O(n)。

关键点解析

  • 以每一个元素结尾的最长等差子序列的长度统统存起来

代码

1
#
2
# @lc app=leetcode.cn id=1218 lang=python3
3
#
4
# [1218] 最长定差子序列
5
#
6
7
# @lc code=start
8
9
10
class Solution:
11
12
# 动态规划
13
def longestSubsequence(self, arr: List[int], difference: int) -> int:
14
n = len(arr)
15
res = 1
16
dp = {}
17
for num in arr:
18
dp[num] = 1
19
if num - difference in dp:
20
dp[num] = dp[num - difference] + 1
21
22
return max(dp.values())
23
24
# @lc code=end
Copied!
复杂度分析
  • 时间复杂度:$O(N)$
  • 空间复杂度:$O(N)$
大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 37K star 啦。 大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。