标签:
时间限制:1000 ms | 内存限制:65535 KB
给定一整型数列{a1,a2...,an}(0<n<=100000),找出单调递增最长子序列,并求出其长度。
如:1 9 10 5 11 2 13的最长单调递增子序列是1 9 10 11 13,长度为5。
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;
}
标签:
原文地址:http://blog.csdn.net/zar123456/article/details/51334735