📜  打印最长的双子序列(空间优化方法)(1)

📅  最后修改于: 2023-12-03 14:54:29.179000             🧑  作者: Mango

打印最长的双子序列(空间优化方法)

概述

双子序列是指一个序列中出现至少两次的子序列,在原序列中两个子序列不能有重叠部分。本文将介绍如何打印出最长的双子序列,同时采用空间优化方法,减小程序的空间占用。

递推关系

假设我们已经求得了前i-1个数的最长双子序列长度li-1和以第i-1个数结尾的最长双子序列长度p-1[i-1]。对于前i个数,最长双子序列长度li可以分两种情况:

  1. 不包含第i个数,则li = li-1。
  2. 包含第i个数,则li = max(p-1[j])+1,其中j表示在前i-1个数中与第i个数相等的最大下标。

对于以第i个数结尾的最长双子序列长度p[i],也有两种情况:

  1. 只有在前i个数中都出现过,才能更新p[i]的值,即p[i] = max(p[j])+1,其中j表示在前i-1个数中与第i个数相等的最大下标。
  2. 在前i-1个数中出现过,但在第i个数中没有出现过,则p[i] = p[i-1]。

综上所述,我们可以得到以下代码:

def print_longest_twin_subsequence(X):
    n = len(X)
    L = [0] * n
    P = [0] * n
    M = {}
    for i in range(n):
        if X[i] in M:
            j = M[X[i]]
            P[i] = L[j] + 1
        else:
            P[i] = 1
        M[X[i]] = i
        for j in range(i):
            if X[i] == X[j]:
                L[i] = max(L[i], P[j])
        L[i] = max(L[i], L[i - 1])
    result = []
    i = n - 1
    while i >= 0:
        if P[i] > 1 and P[i] + L[i - 1] == L[n - 1]:
            result.append(X[i])
            i -= 1
        elif L[i] == L[i - 1]:
            i -= 1
        else:
            i -= 1
    result.reverse()
    return result
空间优化

以上代码时间复杂度为O(n^2),空间复杂度为O(n),而实际上我们只需要前一行和当前行的信息。因此可以将L和P改为两个一维数组,每次计算新一行的信息时,只需要用上一行的信息和当前行的信息即可。这样,空间复杂度就可以优化为O(1)。

def print_longest_twin_subsequence(X):
    n = len(X)
    L0, L1 = 0, 0
    P0, P1 = 0, 0
    M = {}
    for i in range(n):
        if X[i] in M:
            j = M[X[i]]
            P1 = L0 + 1
        else:
            P1 = 1
        M[X[i]] = i
        for j in range(i):
            if X[i] == X[j]:
                L1 = max(L1, P0)
        L1 = max(L1, L0)
        P0, P1 = P1, P0
        L0, L1 = L1, L0
    result = []
    i = n - 1
    while i >= 0:
        if P0 > 1 and P0 + L1 == L0:
            result.append(X[i])
            i -= 1
        elif L0 == L1:
            i -= 1
        else:
            i -= 1
        P0, P1 = P1, P0
        L0, L1 = L1, L0
    result.reverse()
    return result
总结

本文介绍了最长双子序列的递推关系,及空间优化方法。空间优化方法虽然难度比较大,但相比于暴力算法的O(n^2)空间复杂度,O(1)的空间复杂度还是很诱人的。希望本文能对大家的编程学习有所帮助。