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 动态规划法
我们用动态规划的思想来解决这个问题。
- 定义子问题 令 dp[i]来表示以 A[i]结尾的最长递增子序列的长度。dp[i]便是一个前缀,对应一个片段。
- 建立问题的递归关系
- dp[1] = 1
- 拓扑排序
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