具有两个数字的最长增加子序列(LIS)

时间:2012-01-03 18:29:37

标签: algorithm

如何使用两个数字找到LIS的长度。 例如,     [(1,2)(7,8)(3,4)(5,6)] 在上面的数组序列中,LIS的长度为3.即     [(1,2)(3,4)(5,6)] 有什么想法吗?

7 个答案:

答案 0 :(得分:8)

我不确定你在问什么,但我会假设你的意思是一对(a,b)小于另一对(c,d)当且仅当a&lt; c和b < d。

通过采用标准的动态编程技术,可以在O(N ^ 2)时间内轻松解决这一问题,该技术描述为in another SO thread

经典的O(N log N)solution to the standard LIS problem可以扩展为给出LIS问题的子二次解决方案,但有一些困难。我们不能简单地记住每个可能长度的最小值;我们必须维护“阶梯式”结构,其中包含每个长度的所有最小对,即最多N个所描述的数据结构的副本here,使用键入第一个成员的有序动态对集合实现。然后我们可以在O(log N)时间内查询该结构的一个副本(以检查它是否包含少于当前对的任何对),为二进制搜索步骤提供O(log ^ 2 N)时间,并且O(N log ^ 2 N)时间全部。这是我对这个问题最快的解决方案。

答案 1 :(得分:7)

您可以使用任何algorithm作为标准LIS problem,并进行两项修改:

  1. 丢弃第二个数字不严格大于第一个数字的任何对。
  2. 对A和B的比较运算符(即A < B)需要将第二个A与第一个B的数量进行比较。

答案 2 :(得分:0)

我认为您可以使用标准LIS算法,但有一个小例外 -

当您将索引i与索引i + 1进行比较时 - 将i的上限值与i + 1的下限值进行比较。

编辑:这当然是假设所有范围的首先是较低的数字,而下一个是较高的数字。

答案 3 :(得分:0)

将问题建模为图表。每个元组都可以是一个节点。如果第一个元组严格小于第二个元组,则从一个节点到另一个节点存在有向边(这里“less”表示元组的两个值都较小)。

增长最长的子序列现在是此图中最长的路径。请注意,此图中没有循环(即它是DAG)。可以通过动态编程找到DAG中最长的路径(参见wikipedia)。

答案 4 :(得分:0)

继续进行,以便找到简单数组的LIS。只做一次比较,比较两个元素。它将为LIS提供O(n ^ 2)时间复杂度。

答案 5 :(得分:-1)

如果元组中的第一个和第二个数字本身总是在递增(这似乎是你的例子中的情况),除了一些小修改之外,这原则上不应该与regular LIS algorithm不同:只需增加最大LIS直到最后一个数字小于当前元组的第一个数字的当前元组。使用动态编程来缓存每个序列点的最大LIS和前任元组。

答案 6 :(得分:-1)

您必须先找到LIS,然后计算其基数