最长等差数列【LC1027】
给你一个整数数组
nums,返回nums中最长等差子序列的长度。回想一下,
nums的子序列是一个列表nums[i1], nums[i2], ..., nums[ik],且0 <= i1 < i2 < ... < ik <= nums.length - 1。并且如果seq[i+1] - seq[i](0 <= i < seq.length - 1) 的值都相同,那么序列seq是等差的。
最近还挺顺手的
2023/04/22
-
思路:枚举选哪个
每遇到一个数nums[i]nums[i]nums[i],我们需要枚举这个数和前面每个数组成的等差子序列的情况(差值和长度),来更新以nums[i]nums[i]nums[i]结尾的差值为jjj的子序列的长度
-
确定dp数组(dp table)以及下标的含义
dp[i][j]:以nums[i]为末尾的差为j的等差序列的最长长度 -
确定递推公式
对于
dp[i][j],枚举前一位arr[j]arr[j]arr[j],求出由这nums[j],nums[i]nums[j],nums[i]nums[j],nums[i]组成的等差序列的差值divdivdiv,dp[i][k]的状态由dp[j][k]更新,状态转移方程为
dp[i][j]=max(dp[i][k],dp[j][k]+1) dp[i][j]=max(dp[i][k],dp[j][k]+1) dp[i][j]=max(dp[i][k],dp[j][k]+1) -
如何初始化
初始时,子序列只包含当前数字,因此dp数组均为1(也可以初始化为0,最后将答案+1)
-
确定遍历顺序
从小到大枚举iii,然后从大到小枚举jjj
-
举例推导dp数组
-
-
实现
由于差值可能为负数,最小差值为-500,因此需要统一+500
class Solution { public int longestArithSeqLength(int[] nums) { // dp[i][j] 以nums[i]为末尾的差为j的等差序列的最长长度 【负数+500】 int n = nums.length; int res = 0; int[][] dp = new int[n][1010]; for (int i = 0; i < n; i++){ Arrays.fill(dp[i], 1); } for (int i = 1; i < n; i++){ for (int j = 0; j < i; j++){ int div = nums[i] - nums[j] + 500; dp[i][div] = Math.max(dp[i][div], dp[j][div] + 1); res = Math.max(res, dp[i][div]); } } return res; } }-
复杂度
- 时间复杂度:O(nC+n2)O(nC+n^2)O(nC+n2),nnn为数组长度,CCC为定义的状态空间大小,初始化需要的时间复杂度为O(nC)O(nC)O(nC),动态规划的时间复杂度为O(n2)O(n^2)O(n2)
- 空间复杂度:O(nC)O(nC)O(nC)
-
解决最长等差数列问题的动态规划算法

该文章描述了一个使用动态规划解决寻找整数数组中最长等差子序列长度的问题。通过枚举数组元素并计算差值,更新以特定元素结尾的等差序列长度,最终得到最长序列的长度。算法的时间复杂度为O(n^2),空间复杂度为O(nC),其中n为数组长度,C为状态空间大小。

被折叠的 条评论
为什么被折叠?



