最長單調遞減子序列

方法一:普通動態規劃算法,時間複雜度O(n2)。

int LIS(int a[], int n)
{
	int i, j, k;
	int maxlen;
	int *b=new int[n];
	for(i=0, b[0]=1; i<n; i++)
	{
		for(j=0, k=0; j<i; j++)
		{
			if(a[j]>a[i] && k<b[j])
				k=b[j];
			b[i]=k+1;
		}
	}
	
	maxlen=0;
	for(i=0; i<n; i++)
		if(b[i]>maxlen)
			maxlen=b[i];

	return maxlen;
}
int main()
{
	int a[]={9,4,3,2,5,4,3,2};
	cout<<LIS(a, 8)<<endl;
	
}

 

方法二:採用二分搜索算法,時間複雜度O(nlgn)。

 0<=i<n,k是序列a[0:i]的最長單調遞減子序列的長度。b[k]是序列a[0:i]中所有長度爲k的遞減子序列中的最大結尾元素值。

在由i-1到i的循環中,如果a[i]<b[k],則k++,b[k]=a[i];否則k值不變,但要更新b數組。怎麼更新b數組呢?如果a[i]>b[1],則b[1]=a[i];若a[i]<b[1],注意到數組b是遞減的,則二分搜索找到b[j-1]>a[i]>b[j],更新b[j]=a[i]。

 

int LIS(int a[], int n)
{
	int i=0, k;
	int l, h;
	int *b=new int[n+1];
	b[1]=a[0];
	for(i=1, k=1; i<n; i++)
	{
		if(a[i]<b[k]) 
			b[++k]=a[i];
		else
		{//更新b[]
			if(a[i]>b[1]) 
				b[1]=a[i];
			else
			{//二分查找
				for(l=1, h=k; l!=h-1; )
				{
					int mid=(l+h)/2;
					if(b[mid]<=a[i]) 
						h=mid;
					else
						l=mid;
				}
				b[h]=a[i];
			}
		}
	}

	return k;
}

int main()
{
	int a[]={9,4,3,2,5,4,3,2};
	cout<<LIS(a, 8)<<endl;
	
}



 

發佈了90 篇原創文章 · 獲贊 22 · 訪問量 41萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章