如何找到最长增长子序列的实际序列?

时间:2011-10-20 08:55:19

标签: dynamic-programming

这不是一个家庭作业问题。我正在审查自己最长的后续问题。我在线阅读每一个地方。我理解如何找到“长度”,但我不明白如何回溯实际序列。我正在使用耐心排序算法来查找长度。任何人都可以解释如何找到实际的序列?我真的不明白维基百科的版本。有人可以用不同的方法或不同的方式解释吗?

感谢。

2 个答案:

答案 0 :(得分:1)

让我们将max(j)定义为最长的增加子序列,直到A [j]。有两种选择:或者我们在这个子序列中使用A [j],或者我们不使用。[/ p>

如果我们不使用它,那么该值将是max(j-1)。如果我们使用它,那么值就是 max(i)+1,当i是最大的索引时,i< j和A [i]< A [J]。 (这里我们假设max(i)序列使用i-不是必要的true,但是我们可以通过为每个单元格保存2个值 - max(j)值和max *(j)来解决这个问题,当max *( j)是使用A [j]直到A [j]的最长增长子序列。每次将max *(j)计算为max *(i)+1)。

总之,计算max(j)的递归公式将是: max {max(j-1),max *(i)+1},max *(j)= max *(i)+1。 在每个数组单元格中,您可以保存一个指针,告诉您是否选择使用A [j]单元格。 通过这种方式,您可以在阵列上向后移动时找到所有序列。

时间复杂度:递归公式的复杂性和最后查找序列的是O(n)。这里的问题是为每个A [j]找到相应的A [i],使得i是最大的索引,使得i <1。 j,A [i]&lt; A [J]。 当然你可以在O(n ^ 2)中做到天真(从每个单元格向后看,直到你找到这个i)。如果你想做得更好,那么我很确定你可以通过以下方式在O(nlogn)中做到这一点:

*对数组进行排序。 1)选择数组中的最小整数,并将数组中的位置标记为k。

2)对于A [k + 1],我们当然有A [k]&lt; A [K + 1]。如果A [k + 1]> A [k + 2]那么k也将到达k + 2个单元,依此类推,直到我们得到A [k + m] <1。 A [k + m + 1],然后k + m是英尺到k + m + 1,

3)删除您在前一阶段找到相应单元格的所有单元格

4)返回1.

希望它有所帮助。 请注意我一直都在考虑这个因素,因此这里存在一些错误的可能性非常小 - 如果您需要,请确信我是对的并要求更多澄清。

答案 1 :(得分:0)

此Python代码解决了最长递增序列问题,并返回其中一个序列。诀窍是,在动态编程表被填充的同时,另一个数组也被填充,存储用于构建最优解的元素的索引。

def an_lis(nums):
    table, solution = lis_table(nums)
    if not table:
        return (0, [])
    n, maxLen = max(enumerate(table), key=itemgetter(1))
    lis = [nums[n]]
    while solution[n] != -1:
        lis.append(nums[solution[n]])
        n = solution[n]
    return lis[::-1]

def lis_table(nums):
    n = len(nums)
    table, solution = [0] * n, [-1] * n
    for i in xrange(n):
        maxLen, maxIdx = 0, -1
        for j in xrange(i):
            if nums[j] < nums[i] and table[j] > maxLen:
                maxLen, maxIdx = table[j], j
        table[i], solution[i] = 1 + maxLen, maxIdx
    return (table, solution)