算法题10 最长等差序列问题

题目

  给定一个大小为n的数组,要求写出一个算法,求其最长的等差数列的子序列

分析

  该题需要分几种情况考虑。

1. 原数组是有序的,所要求的的子序列可以不连续。

  对于数组arr[],不同的等差值d=1,2,3,4,5```(arr[max]-arr[min])可以求出不同的最长等差数列,然后在这些等差数列中求出最长的那个即可我们首先转化为求一个数组的固定等差值的最长等差子序列。如数组1,2,4,6,8,9,求等差值2的最长等差子序列为2,4,6,8

 1.1 固定等差值的最长子序列

  求符合条件的最长子序列可以用动态规划来做,设dis[i]记录数组arr[]的第1-i个元素子数组的最长等差子序列长度,状态转移方程式:

  dis[i]=1;

  dis[i]=dis[k]+1, k是数组第1-i个元素中,与元素i等差为d并且距离i最近的元素(k<i);

  代码

 1 int RegularArithmeticSeq(int arr[],int len,int d)
 2 {
 3     if (arr==NULL||len<1)
 4         throw std::exception("Invalid input.");
 5 
 6     int* dis=new int[len+1]();
 7 
 8     int re_len=0,re_index=0;
 9     for (int i=1;i<=len;i++)
10     {
11         dis[i]=1;
12         for (int k=i;k>0;k--)
13         {                                                                                      
14             int cur_d=arr[i-1]-arr[k-1];
15 
16             if (cur_d==d&&dis[i]<=dis[k])                                                                                         
17             {
18                 dis[i]=dis[k]+1;
19             }
20 
21             if (re_len<=dis[i])
22             {
23                 re_len=dis[i];
24                 re_index=i;
25             }
26 
27             if (cur_d>d)
28                 break;
29         }
30     }
31 
32     int out=arr[re_index-1];
33     for (int n=0;n<re_len;n++)
34     {
35         cout<<out<<' ';
36         out=out-d;
37     }
38     cout<<endl;
39 
40     delete[] dis;
41 
42     return re_len;
43 }

  上述代码的时间复杂度为O(n*n),时间复杂度为O(n);

  对于寻找1-i中最后一个和i等差的元素k,除了顺序遍历,还可以用二分查找法进行一点优化,查找的时间复杂度为O(logn)

 1</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值