牛客-Arithmetic Progressions(dp优化)

该博客介绍了如何使用动态规划解决寻找数组中最长等差数列的问题。代码实现中,通过双指针优化了时间复杂度,最终找到并输出最长等差数列的长度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在这里插入图片描述

题意

给你 n 个数,让你从中找出最长的等差序列

思路

dp求最长等差数列的长度
dp [ i ] [ j ] :以第 i 个数为倒数第二位,第 j 个数为倒数第一位的等差序列的长度;
转移方程 dp [ i ] [ j ] = dp [ k ] [ i ] + 1;
如果 n > = 2 , 那么等差序列最短长度也是 2 ,所以 dp 初始化可以初始化为 2 .

代码
#include<iostream>
#include<string>
#include<map>
#include<set>
//#include<unordered_map>
#include<queue>
#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
#include<iomanip>
#include<cmath>
#include<fstream>
#define X first
#define Y second
#define best 131 
#define INF 0x3f3f3f3f
#define P pair<int,int>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const double eps=1e-7;
const double pai=acos(-1.0);
const int N=2e4+10;
const int maxn=4e5+10;
const int mod=1e9+7;
//const int d[4][2]={0,1,1,0,-1,0,0,-1};
int dp[5010][5010];
int n,a[5010];
int main(){
	//ios::sync_with_stdio(false);
    scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    sort(a,a+n);
    for(int i=0;i<n-1;i++)
    {
    	for(int j=i+1;j<n;j++)
    	{
    		dp[i][j]=2;
		}
	}
    int maxx=2;
    for(int i=1;i<n-1;i++)
	{
    	int j=i+1,k=i-1;//这里是优化了一下(如果不优化会 T ,原来是三层循环)
    	//因为 k < i < j ,我们可以直接让j从i+1递增,k从i-1递减,这样就变成了两层,时间复杂度大大降低
    	while(k>=0&&j<n)
		{
    		if(a[j]-a[i]==a[i]-a[k])//差值相等,说明正好,更新 dp 
			{
				dp[i][j]=dp[k][i]+1;
				if(dp[i][j]>maxx) maxx=dp[i][j];
				k--,j++;
			}
			else if(a[j]-a[i]<a[i]-a[k]) j++;
			else k--;
			//差值不相等,往小的方向移动,因为移动后小的差值才会变大
		}
    }
    printf("%d",maxx);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值