您的位置:首页 > 其它

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

2016-05-06 21:22 232 查看


单调递增子序列(二)

时间限制: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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: