一个更简单的问题是找到最长递增子序列的长度。你可以先专注于理解这个问题。该算法的唯一区别是它不使用P数组。
x是一个序列的输入,所以可以初始化为:x = [0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15]
m跟踪迄今为止找到的每个长度的最佳子序列。最好的是具有最小结束值的那个(允许在其后添加更广泛的值)。长度和结束值是每个子序列需要存储的唯一数据。
m的每个元素代表一个子序列。对于m[j],
- j是子序列的长度。
- m[j]是子序列最后一个元素的索引(在x中)。
- 所以,x[m[j]]是子序列的最后一个元素的值。
L是迄今为止发现的最长子序列的长度。m的前L个值是有效的,其余的是未初始化的。m可以从第一个元素为 0 开始,其余未初始化。L随着算法的运行而增加,m的初始化值的数量也会增加。
这是一个示例运行。x[i],并且在每次迭代结束时给出m (但使用序列的值而不是索引)。
每次迭代中的搜索都在寻找放置x[i]的位置。它应该尽可能向右(以获得最长的序列),并且大于其左侧的值(因此它是一个递增序列)。
0: m = [0, 0] - ([0] is a subsequence of length 1.)
8: m = [0, 0, 8] - (8 can be added after [0] to get a sequence of length 2.)
4: m = [0, 0, 4] - (4 is better than 8. This can be added after [0] instead.)
12: m = [0, 0, 4, 12] - (12 can be added after [...4])
2: m = [0, 0, 2, 12] - (2 can be added after [0] instead of 4.)
10: m = [0, 0, 2, 10]
6: m = [0, 0, 2, 6]
14: m = [0, 0, 2, 6, 14]
1: m = [0, 0, 1, 6, 14]
9: m = [0, 0, 1, 6, 9]
5: m = [0, 0, 1, 5, 9]
13: m = [0, 0, 1, 5, 9, 13]
3: m = [0, 0, 1, 3, 9, 13]
11: m = [0, 0, 1, 3, 9, 11]
7: m = [0, 0, 1, 3, 7, 11]
15: m = [0, 0, 1, 3, 7, 11, 15]
现在我们知道有一个长度为 6 的子序列,以 15 结尾。子序列中的实际值可以通过在循环期间将它们存储在P数组中来找到。
检索最佳子序列:
P将每个数字的前一个元素存储在最长子序列中(作为 x 的索引),并随着算法的推进而更新。例如,当我们处理 8 时,我们知道它在 0 之后,因此将 8 在 0 之后的事实存储在P中。您可以像链表一样从最后一个数字向后工作以获取整个序列。
因此,对于每个数字,我们都知道它之前的数字。为了找到以 7 结尾的子序列,我们查看P并看到:
7 is after 3
3 is after 1
1 is after 0
所以我们有子序列 [0, 1, 3, 7]。
以 7 或 15 结尾的子序列共享一些数字:
15 is after 11
11 is after 9
9 is after 6
6 is after 2
2 is after 0
所以我们有子序列 [0, 2, 6, 9, 11] 和 [0, 2, 6, 9, 11, 15](最长的递增子序列)