您的位置:首页 > 其它

最长上升子序列的两种方法

2016-04-25 21:56 459 查看

最长上升子序列

一个序列,比如说a[]={1,7,3,5,9,4,8},找出它的最长上升子序列的个数,很明显是4个,可以是{1,3,5,9},{1,3,5,8}或者{1,3,4,8}。具体怎么实现呢?直观的感受是以1为起点,下一个数比1大,那么上升子序列个数就+1,以1为起点,到7的时候,上升子序列的个数是2;到3的时候也是2,因为3>1&&3<7;再遍历下一个数5,5与1比较大于1,上升子序列的个数为2,再与7比较,5<7,子序列个数不变,再与3比较,5>3,上升子序列的个数+1,为3,以此类推,那么程序的流程大致为:

定义数组b[]用来存放a[]中每个数的上升子序列的个数,找出b[]中最大值。

#include <iostream>
using namespace std;
int main()
{
int a[] = { 1, 7, 3, 5, 9, 4, 8 };
int n = sizeof(a) / sizeof(int);
int b[sizeof(a) / sizeof(int)];
b[0] = 1;
for (int i = 1; i < n;i++)
{
b[i] = 1;
for (int j = 0; j < i;j++)
{
if (a[i]>a[j] && b[j] + 1>b[i])
b[i] = b[j] + 1;
}
}
int maxb = 0;
for (int i = 0; i < n;i++)
{
if (maxb < b[i])
maxb = b[i];
}
cout << maxb << endl;
return 0;
}


上述算法的时间复杂度是O(n^2)

下面这种方法的时间复杂度是O(nlogn)。具体的方法是:采用b[]数组用来存放上升子序列(上面的方法是用来存放当前数的最大上升子序列),还是a[]={1,7,3,5,9,4,8},想要找出最长的子序列,那么每一个值都要尽可能小,比如说{1,3}一定比{1,7}好,那么,在遍历到7的时候,b[]={1,7},这时遍历3,3比7小(3的潜力更大),应该用3代替7,也就是在数组b[]={1,7}中找到3的位置,采用二分法(时间 复杂度O(logn))。具体程序:

#include <iostream>
using namespace std;
int BinSeach(int &item, int *a, int left, int right)
{
while (left<right)
{
int mid = (left + right) / 2;
if (item > a[mid] && item <= a[mid + 1])
return mid;
else if (item < a[mid])
right = mid - 1;
else
left = mid + 1;
}
}
int main()
{
int a[] = { 1, 7, 3, 5, 9, 4, 8 };
int n = sizeof(a) / sizeof(int);
int b[sizeof(a) / sizeof(int)];
b[0] = a[0];
int len = 1;
int j = 0;
for (int i = 1; i < n;i++)
{
if (a[i]>b[len - 1])
j = len++;
else
j = BinSeach(a[i], b, 0, len - 1)+1;
b[j] = a[i];
}
cout << len << endl;
for (int i = 0; i < len;i++)
{
cout << b[i] << " ";
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: