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

来源:互联网 发布:乐高机器人的所有编程 编辑:程序博客网 时间:2024/05/22 01:29

最长上升子序列

一个序列,比如说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;}
1 0
原创粉丝点击