【算法】最长递增子序列问题

1.问题描述

有一个序列 A = [18, 17, 19, 6, 11, 21, 23, 15],求出最长递增子序列的个数。

2.算法描述

该问题解唯一,但解的形式不唯一。譬如,该问题最长递增子序列的个数为 4,但最长递增 子序列可以有多种情况,比如[18, 19, 21, 23]、[17, 19, 21, 23]、[6, 11, 21, 23]。

2.1 枚举法

对于这个问题,可以用最原始的方法来枚举每一种情况,每个元素都有取和不取两种选择。 但在此算法中,如果元素有 n 个,那么该算法的时间复杂度将高达 O(2^n)。

2.2 动态规划法

我们用动态规划的思想来解决这个问题。

  1. 定义子问题 令 dp[i]来表示以 A[i]结尾的最长递增子序列的长度。dp[i]便是一个前缀,对应一个片段。
  2. 建立问题的递归关系
    在这里插入图片描述
  3. dp[1] = 1
  4. 拓扑排序
    在这里插入图片描述

3. 实验代码

if __name__ == "__main__": 
	LIS = [] 
	A = [18,17,19,6,11,21,23,15] 
	dp = [[1,-1],[1,-1],[1,-1],[1,-1],[1,-1],[1,-1],[1,-1],[1,-1]] #边界初始条件 
	#按顺序计算出 dp[i]的值 
	for i in range(1,len(A)): 
		for j in range(0,i): 
			if (A[j] < A[i]) and (dp[j][0] + 1 > dp[i][0]): 
				#状态转移方程,更新 dp[i] 
				dp[i][0] = dp[j][0] + 1 
				dp[i][1] = j 
	maxLength = max(dp) 
	#print(A) 
	#print(dp) 

	index = maxLength[1] 
	for j in range(maxLength[0]): 
		LIS.append(A[index]) 
		index = dp[index][1] 
	LIS.reverse() 
	print("该序列为:",LIS) 
	print("该序列最长递增子序列的长度为:",maxLength)

4. 实验结果

由下图结果可知,该序列最长递增子序列的长度为 4,这与我们的预期相符。
在这里插入图片描述

参考和致谢

[1]胡凡,曾磊.算法笔记[M].机械工业出版社:北京,2016.7:390-392.
[2]算法分析和设计 http://www.icourse163.org/spoc/learn/ZJUT-1460190163?tid=1460863458#/learn/conte nt

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值