在这里用最简单的思路,时间复杂度为O(n^3)
思路:我们知道任意取2个元素,都能构成一个长度为2的等差数列,比如:a,b就等构成一个长度为2的,首元素为a,差为b-a的等差数列。
但是三个数:a,b,c(有序)就不一定了,因为c-b和b-a未必相等。
所以我们可以穷举出数列的前2个元素a[i], a[j],因为2个数必然构成一个等差数列,差为diff = a[j]-a[i]。然后j后面的元素中,找到一个a[k]使得a[k] = a[j]+diff,然后后在k后面找到a[n] = a[k]+diff,最后知道到达数组尾部。
我们可以定义一个变量length统计这个数列的最大长度,并且和已知的最大长度max比较,如果比Max大,就更新max = length。
同样我们可以定义一个stack来记录当前这个数列中的元素,并且定义另一个栈maxstack记录目前已知的最大长度的数列所包含的元素。
当遇到length>max的话,那说明maxstack也要重新赋值,所以我们就清空maxstack里原来的记录,用当前stack中记录的最长数列,去更新maxstack.
#include "stdafx.h"
#include<iostream>
#include<algorithm>
#include<stack>
using namespace std;
void clear(stack<int> &ss)//清空栈
{
while(ss.size()>0)
ss.pop();
}
void copy(stack<int> ss,stack<int> &max)//用栈ss的内容去赋值max栈
{
while(!ss.empty())
{
max.push(ss.top());
ss.pop();
}
}
int longest(int a[], int len)//求最长的等差数列
{
sort(a,a+len);//先对数组进行排序
unsigned int max = 1;//记录最长的等差数列的长度
stack<int> ss;//记录当前等差数列的元素
stack<int> maxstack;//记录目前已知的最长等差数列的元素
for(int i=0;i<len;i++)//等差数列的第一个元素
{
ss.push(a[i]);//第一个元素入栈
for(int j=i+1;j<len;j++)//等差数列的第二个元素
{
ss.push(a[j]);//第二个元素入栈
int diff = a[j] - a[i];//公差
int base = a[j];//这个是查找下一个元素用
//int length = 2;
for(int k = j+1;k<len;k++)
{
if(a[k] == (base+diff))//如果当前等差数列的下一个元素是a[k]
{
ss.push(a[k]);//a[k]入栈
//length++;
base = a[k];//更新base为当前元素,查找下一个元素base+diff即可
}
}
if(ss.size()>max)//如果当前得到的最长数列,比已知的最长数列长
{
max = ss.size();//更新最长长度
clear(maxstack);//清空maxstack
copy(ss,maxstack);//更新最长数列的所有元素
}
while(ss.size()>1)//重新选择第二个元素a[j],所以需要pop所有元素只留下第一个
{
ss.pop();
}
}
clear(ss);//清空ss,重新选择第一个元素a[i]
}
while(maxstack.size()>0)//输出最长的数列
{
cout<<maxstack.top()<<" ";
maxstack.pop();
}
cout<<endl;
return max;
}
int main()
{
int a[] = {1,3,0,5,-1,-6};
int len = sizeof(a)/sizeof(int);
cout<<longest(a,len)<<endl;
getchar();
return 0;
}