📅  最后修改于: 2023-12-03 14:54:29.179000             🧑  作者: Mango
双子序列是指一个序列中出现至少两次的子序列,在原序列中两个子序列不能有重叠部分。本文将介绍如何打印出最长的双子序列,同时采用空间优化方法,减小程序的空间占用。
假设我们已经求得了前i-1个数的最长双子序列长度li-1和以第i-1个数结尾的最长双子序列长度p-1[i-1]。对于前i个数,最长双子序列长度li可以分两种情况:
对于以第i个数结尾的最长双子序列长度p[i],也有两种情况:
综上所述,我们可以得到以下代码:
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)的空间复杂度还是很诱人的。希望本文能对大家的编程学习有所帮助。