动态规划: 最长上升子序列(LIS)


学习动态规划问题(DP问题)中,其中有一个知识点叫最长上升子序列(longes increasing subsequence),也可以叫最长非降序子序列,简称LIS。简单说一下自己的心得。

关于这个问题,之所以能用动态规划来解决,只因为其满足动态规划的条件,当前解可以由上一个阶段的解推出

建立状态转移方程,就能把大的问题转化为小的问题,进而逐渐缩小规模,直至解决。

分析:设有n个数的最长上升子序列长度为f(n),我们要求f(n),可以先求f(n-1),再对n做判断,反复判断,直至n=1,我们可以知道f(1)=1;



具体做法:a[n]储存n个数,维护一个一维数组dp[I],dp[I]表示前I个数的LIS,每加入一个数a[I],找出满足(j<I&&a[j]<a[I])的最大的dp[j],即找出当前能让a[I]加入的最长的序列,然后加一,即dp[I]=max(dp[I],dp[j]j<I&&a[j]<a[I])+1.


代码如下:(有重复元素)

int LIS(int a[], int n){                              //传入一个大小为n的数组,返回最长上升子序列长度,允许含相同元素
	int dp[n];
	for(int i = 0; i < n; i++){                   //初始化,还没判断时,对于每个dp【i】都是只有a【i】的长度为1的序列
		dp[i] = 1;
	}
	for(int i = 0; i < n; i++){                    //外循环遍历a【i】
		for(int j = 0; j < i; j++){            //内循环找出满足a[j]<a[i]的最大dp【i】
			if(a[j] < a[i]){
				dp[i] = max(dp[i], dp[j]) + 1;
			}
		}
	}
	int mmax = 0;
	for(int i = 0; i < n; i++){
		if(dp[i] > mmax){
			mmax = dp[i];
		}
	}
	return mmax;
} 

上述算法通过两个循环不难看出复杂度为O(n2),可以通过优化使复杂度降低到O(nlogn),方法时将内循环搜索改为二分查找,这样二分查找复杂度为logn,可以大大提高速度。但二分需有序,因此我们换一种dp数组的表示意义。


具体做法:同样是a[i]储存n个数,不同的是维护的数组dp1[i]表示的是LIS长度为i的序列最小的结尾值,最后输出dp数组的长度即为所求。比较见下表:

a[0] a[1] a[2] a[3] a[4] a[5] a[6]
1 7 3 5 9 4 8
dp[0] dp[1] dp[2] dp[3] dp[4] dp[5] dp[6]
2 2 3 4 3 4
dp1[0] dp1[1] dp1[2] dp1[3] dp1[4] dp1[5] dp1[6]
1 3 4 8 0 0 0

代码如下:(有重复元素)

int lis(int a[], int n){
	int dp[N];
	dp[0] = a[0];
	int len = 0;
	for(int i = 1; i < n; i++){
		if(a[i] >= dp[len]){
			dp[++len] = a[i];
		}else{
			int k = upper_bound(dp, dp+len+1, a[i])-dp;
			dp[k] = a[i];
		}
	}
	return len+1;
}

(无重复元素):

int LIS(int a[], int n){
	int dp[N];
	dp[0] = a[0];
	int len = 0;
	for(int i = 1; i < n; i++){
		if(a[i] > dp[len]){
			dp[++len] = a[i];
		}else{
			int k = lower_bound(dp, dp+len+1, a[i])-dp;   
			dp[k] = a[i];
		}
	}
	return len+1;
}

注意有无重复元素代码的红色部分。

upper_bound与lower_bound的比较
首先,最形象的一句话:
upper_bound(i) 返回的是键值为i的元素可以插入的最后一个位置(上界)
lowe_bound(i) 返回的是键值为i的元素可以插入的位置的第一个位置(下界)。
举例说明
1 2 4 5 中插入3都是返回位置3
1 3 3 4 中插入3upper_bound就返回位置4而lower_bound返回的是位置2

猜你喜欢

转载自blog.csdn.net/godjing007/article/details/81047330