标签:
时间限制: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