码迷,mamicode.com
首页 > 其他好文 > 详细

最长单增子序列问题

时间:2015-01-30 22:56:15      阅读:259      评论:0      收藏:0      [点我收藏+]

标签:动态规划   lis   

      问题描述:有一个长为n的数列a0,a1,a2........a(n-1)。请求出这个序列中最长的单增子序列的长度。单增子序列的定义是:对于任意的 i<j,都满足ai<aj。

      这个问题就是著名的最长单增子序列(LIS)问题。对于这道问题,我们可以利用动态规划来进行求解:假设dp[i]表示以a[i]为末尾的最长单增子序列的长度,则在得到dp[i]时,我们可以这样做:初始化dp[i]为1,利用一个j变量遍历已经访问过的数组a中的值,如果此时a[i]>a[j],表示我们可以在原来的子序列之后加上一个构成一个新的以ai结尾的单增子序列,这时,如果dp[i]的值小于dp[j]+1的值时,我们就将其更新。这样我们就可以得到:时间复杂度为O(n^2)。

                         dp[i] = max{dp[j] + 1, 1} if j<i and a[j] < a[i]

#include<iostream>
#define max(a, b) ((a)>(b)?(a):(b))

const int INF = 1000000;
const int n = 6;
int a[n] = {4, 2, 3, 1, 5, 5};

int dp[n];

/**
dp[i]表示以a[i]为末尾的最长单增子序列的长度
*/
int dp1(){
	int res = 0;
	for (int i = 0; i < n; i++){
		dp[i] = 1;
		for (int j = 0; j < i; j++)
		{
			if (a[i] > a[j])
			{
				dp[i] = max(dp[i], dp[j]+1);
			}
		}
		res = max(dp[i], res);
	}

	return res;
}

int main(){
	printf("%d\n", dp1());
	system("pause");
	return 0;
}
       接下来我们换一种思路来想,如果子序列的长度相同的话,那么取得的末尾值越小就越有优势。基于这种思路我们可以利用这样的假设:dp[i]表示长度为i+1的上升子序列中末尾元素的最小值。首先我们对dp数组用无穷大INF进行初始化,对于每一个ai,如果j==0,或者dp[j-1]<a[i],我们就用dp[j] = min(dp[j], a[i])来进行更新。这样我们仍然需要一个两层的循环,但是可以进行优化,对于内层的循环:由于dp数组是单增的(可以用反证法证明,如果i<j,而dp[i] > dp[j],则在以dp[j]结尾的单增子序列中的第i位一定小于dp[i],这样就违背了当初对dp数组的假设),我们可以使用一个二分搜索来找的我们需要更新的位置,即在dp数组中找到大于或等于a[i]且最近的位置,这样就将时间复杂度降低为O(n*logn)。

#include<iostream>
#define max(a, b) ((a)>(b)?(a):(b))

const int INF = 1000000;
const int n = 6;
int a[n] = {4, 2, 3, 1, 5, 5};

int dp[n];

/*
返回dp数组中找到>=target且最近的位置
*/
int binary_search(int target){
	int l = -1, r = n, m;

	while(l+1 != r){
		m = (l+r)/2;
		if (dp[m] < target)
			l = m;
		else
			r = m;
	}
	return r;
}

/**
dp[i]表示长度为i+1的上升子序列中末尾元素的最小值
*/
int dp2(){

	for (int i = 0; i < n; i++)
	{
		dp[i] = INF;
	}
	for (int i = 0; i < n; i++)
	{
		int p = binary_search(a[i]);
		dp[p] = a[i];
	}

	return binary_search(INF);
}

int main(){
	printf("%d\n", dp2());
	system("pause");
	return 0;
}


      

最长单增子序列问题

标签:动态规划   lis   

原文地址:http://blog.csdn.net/smbroe/article/details/43307509

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!