求数组中最长递增子序列

《编程之美》第2.16节:求数组中最长递增子序列

问题:写一个时间复杂度尽可能低的程序,求一个一维数组(N个元素)中最长递增子序列的长度。

解法:可以暴力求解,复杂度为O(N^2),另外可以开辟一个数组maxV,其中maxV[i]存放长度为i的递增子序列最大的元素的最小值,用二分法搜索maxV元素,从而使复杂度能够降到O(NlogN)。

代码:

#include<iostream>
#include<algorithm>
using namespace std;

int lowerBinarySearch(int A[],int N,int val)
{
	int lo=0,hi=N;
	while(lo<hi)
	{
		int mid=(lo+hi)/2;
		if(A[mid]>=val)
			hi=mid;
		else
			lo=mid+1;
	}
	return A[lo]>=val?lo-1:lo;
}

int longestIncreaseSubarray(int *A,int N)
{
	if(N<=1)
		return N;
	int *maxV=new int[N+1];
	maxV[1]=A[0];
	maxV[0]=INT_MIN;
	int *lis=new int[N];
	for(int i=0;i<N;i++)
		lis[i]=1;
	int nMaxLis=1;
	for(int i=1;i<N;i++)
	{
		int j;
		j=lowerBinarySearch(maxV,nMaxLis,A[i]);
		lis[i]=j+1;

		if(lis[i]>nMaxLis)
		{
			nMaxLis=lis[i];
			maxV[lis[i]]=A[i];
		}
		else if(maxV[j]<A[i] && A[i]<maxV[j+1])
			maxV[j+1]=A[i];
	}
	return nMaxLis;
}

int longestIncreaseSubarrayNN(int *A,int N)
{
	if(N<=1)
		return N;
	int *lis=new int[N];
	for(int i=0;i<N;i++)
	{
		lis[i]=1;
		for(int j=0;j<i;j++)
		{
			if(A[j]<A[i] && lis[j]+1>lis[i])
				lis[i]=lis[j]+1;
		}
	}
	int result=0;
	for(int i=0;i<N;i++)
		if(lis[i]>result)
			result=lis[i];
	return result;
}

int main()
{
	const int N=10000;
	int A[N]={};
	generate(A,A+N,rand);
	int result=longestIncreaseSubarray(A,N);
	int resultNN=longestIncreaseSubarrayNN(A,N);
	cout<<result<<endl;
	cout<<resultNN<<endl;

	system("pause");
	return 0;
}
为了验证算法的有效性,这里将暴力算法结果也同时输出了,这样能够对比说明算法的正确性。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值