NYOJ 214 最长上升子序列(二)

单调递增子序列(二)

时间限制:1000 ms  |  内存限制:65535 KB


描述

给定一整型数列{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型整数)!
输出
对于每组测试数据输出整形数列的最长递增子序列的长度,每个输出占一行。
样例输入
7
1 9 10 5 11 2 13
2
2 -1
样例输出
5
1


分析:看到这个题与 最长上升子序列(一)相似,于是就用了递推去做,但是超时,对时间要求高,所以想到了二分法去查找可以节省很多时间。

二分法查找

二分法查找其实就是折半查找,一种效率较高的查找方法。针对有需数组来查找的。

主要思想是:(设查找的数组期间为array[low, high])

(1)确定该期间的中间位置K

(2)将查找的值T与array[k]比较。若相等,查找成功返回此位置;否则确定新的查找区域,继续二分查找。区域确定如下:

a.array[k]>T 由数组的有序性可知array[k,k+1,……,high]>T;故新的区间为array[low,……,K-1]

b.array[k]<T 类似上面查找区间为array[k+1,……,high]。每一次查找与中间值比较,可以确定是否查找成功,不成功当前查找区间缩小一半。递归找,即可。

时间复杂度:O(log2n);

代码实现:

        /// <summary>

        /// 二分法查找

        /// </summary>

        /// <param name="array">目标数组(已经排序好了)</param>

        /// <param name="a">查找的数</param>

        /// <returns>目标数的索引</returns>

        public int BinarySearch(int[] array, int T)

        {

            int low, high, mid;

            low = 0;

            high = array.Length - 1;

            while (low <= high)

            {

                mid = (low + high) / 2;

                if (array[mid] < T)

                {

                    low = mid + 1;

                }

                else if (array[mid]>T)

                {

                    high = mid - 1;

                }

                else

                {

                    return mid;

                }

            }

           return -1;

       }


当然 二分法也可以用于排序,由兴趣的可以在网上查找资料。


 
#include<stdio.h>
#include<string.h>
int m[100010],a[100010];
int BSearch(int a[], int n, int t)
{
    int low = 1;
    int high = n;
    while (low <= high)     //结束条件
    {
        int mid = (low + high) / 2;
        if (t == a[mid])
            return mid;
        else if (t > a[mid])
            low = mid + 1;
        else
            high = mid - 1;
    }
    return low;
}

int LIS_BSearch(int a[], int m[], int n)
{
    int maxlen = 1;     //最长上升子序列的长度
    m[maxlen] = a[1];

    int i;
    for (i = 2; i <= n; i++)
    {
        if (a[i] > m[maxlen])
                m[++maxlen] = a[i];

        else
        {
            int p = BSearch(m, maxlen, a[i]);//返回小于a[i]的最大值的位置p
            m[p] = a[i];
        }

    }

    return maxlen;
}

    int main()
    {
        int t;
       while(~ scanf("%d",&t))
       // while(t--)
        {
            int i,j,n,l=0;
            memset(m,0,sizeof(m));
            memset (a,0,sizeof(a));
          //  scanf("%d",&n);
            for(i=1; i<=t; i++)
                scanf("%d",&a[i]);
          l=LIS_BSearch(a,m,t);
          printf("%d\n",l);
        }
        return 0;
    }
        


你可能感兴趣的:(NYOJ 214 最长上升子序列(二))