找到增长最快的序列

pap*_*ppu 38 algorithm lcs

您将获得一系列数字,您需要从给定输入中找到最长的增加子序列(不必连续).

我找到了这个链接(维基百科上增长最快的子序列)但需要更多解释.

如果有人能帮助我理解O(n log n)实现,那将非常有用.如果你能用一个例子解释算法,那将非常感激.

我也看到了其他帖子,我不明白的是:L = 0表示i = 1,2,...... n:二元搜索最大正j≤L,使得X [M [j]] <X [i](或设置j = 0,如果没有这样的值存在)上面的语句,从哪里开始二进制搜索?如何初始化M [],X []?

fgb*_*fgb 98

一个更简单的问题是找到最长的增长子序列的长度.您可以首先专注于理解该问题.算法的唯一区别是它不使用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]
Run Code Online (Sandbox Code Playgroud)

现在我们知道有一个长度为6的子序列,以15结尾.子序列中的实际值可以通过在循环期间将它们存储在P数组中找到.

检索最佳子序列:

P将前一个元素存储在每个数字的最长子序列(作为x的索引)中,并随着算法的进展而更新.例如,当我们处理8时,我们知道它在0之后,因此存储8在P之后为0的事实.您可以从最后一个数字向后工作,如链接列表,以获得整个序列.

因此,对于每个数字,我们知道它之前的数字.为了找到以7结尾的子序列,我们看看P并看到:

7 is after 3
3 is after 1
1 is after 0
Run Code Online (Sandbox Code Playgroud)

所以我们有子序列[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
Run Code Online (Sandbox Code Playgroud)

所以我们有子序列[0,2,6,9,11]和[0,2,6,9,11,15](最长的子序列)

  • 这比维基百科的解释要好得多 (18认同)
  • @pappu:如果答案对你有用,你应该考虑"接受答案".这是通过点击此答案的投票数下方的箭头来完成的. (7认同)
  • 如果OP正在读取,则使用二进制搜索来获取可以在M中插入被考虑的元素的位置.您可以在O(N)中迭代M但是最好是使用二分搜索的O(logN),因为M是增加序列. (4认同)
  • @j_random_hacker M中没有足够的信息.对于输入[5,6,2],最长的序列是[5,6],但长度1的最佳序列是[2],所以M = [0,2, 6] - 它不包含5,因为它被较小的值覆盖. (4认同)
  • fgb !!! 哇 !!!你很棒 !!!!我明白它是如何工作的......我真的要感谢你,当然还有Jeffrey Greenham和sleske的快速反应! (2认同)