最大等差数列子集

我怕爱的太早我们不能终老 提交于 2020-02-23 01:15:14

13 最大等差数列子集

描述

一个等差数列是指以增序排列后,相邻的两个数后一个与前一个数之差值恒定。规定一个等差数列中的数不应少于3个。任给 n ( 2 < n < 5000)个正整数,请判断可否从中选择子集构成等差数列。若能,则选出满足条件的最大子集合(即,元素个数最多),并按从小到大输出子集中的元素,逗号间隔。若有多个子集同时满足最大,则取差值最大的子集;若同时有多个子集满足集合大小最大,且差值也相等,则取起始元素最大的子集。如果没有满足条件的子集合,则输出 NO.

关于输入

第1行,n,表示整数个数;
第2行,n 个正整数,空格间隔;

关于输出

按增序输出最长等差数列子集,逗号间隔。

例子输入
10
20 14 6 15 22 7 23 8 18 25
例子输出
7,15,23
分析

​ 显而易见的,我们首先要对这个序列排序。在这里我们需要对[][][结尾元素序号][数列公差]进行dp,递推公式

diff=arr[i]arr[j]diff = arr[i] - arr[j ] dp[i][diff]=dp[j][diff]+1;dp[i][diff] = dp[j][diff] + 1;

​ 本题略有特殊的地方在于,之前的程序里,我们对什么dp,就在循环体里面对这两个东西进行遍历,而在这里我们进行一些优化,不再对diffdiff 进行遍历,而是对ii之前的所有位置进行遍历,对于每一个jj得到一个diffdiff进行dp

代码实现
#include<iostream>
#include<algorithm>
int dp[5000][5000] = { 0 };//dp[结尾元素][数列公差]
using namespace std;
int main()
{
	int n;
	int arr[5000] = { 0 };
	cin >> n;
	for (int i = 0; i < n; ++i)
		cin >> arr[i];
	sort(arr, arr + n);//排序
	int dist = arr[n - 1] - arr[0];//最大公差
	for (int i = 0; i < n; ++i)
		for (int j = 0; j <= dist; ++j)
			dp[i][j] = 1;//初始化:单个元素的长度为1
	int max_len = 0, max_k = 0, max_e = 0;
	for (int i = 0; i < n; ++i)//对以arr[i]结尾的某个等差数列
	{
		for (int j = 0; j < i; ++j)//在i之前的,以arr[j]结尾的某个等差数列
		{
			int diff = arr[i] - arr[j];//这个等差数列的公差是diff
			dp[i][diff] = dp[j][diff] + 1;//其实还需要一个比较最大值的步骤,但是在这里,我们显然有在同一个公差下,数列的长度有 后面的>=前面的,故而直接赋值即可
			if (max_len < dp[i][diff])//数列长度最优先,强制更新公差、末项
			{
				max_len = dp[i][diff];
				max_k = diff;
				max_e = arr[i];
			}
			else if (max_len == dp[i][diff])//数列长度相等,如果公差比现在的公差小,强制更行末项
			{
				if (max_k < diff)
					max_k = diff, max_e = arr[i];
				else if (max_k == diff)//数列长度、公差都相等,选择性更新末项
					max_e = max_e > arr[i] ? max_e : arr[i];
			}
		}
	}
//以下是输出结果,略
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!