南阳ACM214单调递增子序列(二)

来源:互联网 发布:国密算法sm2 java 编辑:程序博客网 时间:2024/05/16 09:37
时间限制:1000 ms  |  内存限制:65535 KB
难度:4
描述

给定一整型数列{a1,a2...,an}(0<n<=100000),找出单调递增最长子序列,并求出其长度。

如:1 9 10 5 11 2 13的最长单调递增子序列是1 9 10 11 13,长度为5。

输入
有多组测试数据(<=7)
每组测试数据的第一行是一个整数n表示序列中共有n个整数,随后的下一行里有n个整数,表示数列中的所有元素.每个整形数中间用空格间隔开(0<n<=100000)。
数据以EOF结束 。
输入数据保证合法(全为int型整数)!
输出
对于每组测试数据输出整形数列的最长递增子序列的长度,每个输出占一行。
样例输入
71 9 10 5 11 2 1322 -1
样例输出
51

这是一道经典的单调递增子序列的算法题目,如果直接用动态规划的话,时间复杂度为O(logn*n),这样的时间复杂度,会造成超时。所以必须采取另外的方法做这道题目。

参考代码:

 #include <stdio.h>#include <stdlib.h>#include <string.h>#include <iostream>using namespace std;int LIS(int *array, int n); int BiSearch(int *b, int len, int w); int p[100009];int B[100009];int len;int main(){    int n;    while (scanf("%d", &n) != EOF)    {        for (int i = 0; i < n; ++ i)        {            scanf("%d", &p[i]);        }        len = 0;        printf("%d\n", LIS(p, n));    }}int LIS(int *array, int n){    len = 1;    B[0] = array[0];    int i, pos = 0;    for(i=1; i<n; ++i)    {        if(array[i] > B[len-1]) //如果大于B中最大的元素,则直接插入到B数组末尾        {            B[len] = array[i];            ++len;        }        else        {            pos = BiSearch(B, len, array[i]); //二分查找需要插入的位置            B[pos] = array[i];        }    }    return len;}//修改的二分查找算法,返回数组元素需要插入的位置。int BiSearch(int *b, int len, int w){    int left = 0, right = len - 1;    int mid;    while (left <= right)    {        mid = left + (right-left)/2;        if (b[mid] > w)            right = mid - 1;        else if (b[mid] < w)            left = mid + 1;        else    //找到了该元素,则直接返回            return mid;    }    return left;//数组b中不存在该元素,则返回该元素应该插入的位置}        

算法参考的地方:

http://qiemengdao.iteye.com/blog/1660229


0 0
原创粉丝点击