最长等差数列子序列问题如下。给定一个整数数组 A,设计一个算法来找到其中最长的等差数列。也就是说找到一个序列i1 < i2 < … < ik,使得A[i1], A[i2], …, A[ik]形成一个等差级数,并且k是最大的。下面的代码在O(n^2)时间和空间上解决了这个问题。 (修改自 http://www.geeksforgeeks.org/length-of-the-longest-arithmatic-progression-in-a-sorted-array/ 。)
#!/usr/bin/env python
import sys
def arithmetic(arr):
n = len(arr)
if (n<=2):
return n
llap = 2
L = [[0]*n for i in xrange(n)]
for i in xrange(n):
L[i][n-1] = 2
for j in xrange(n-2,0,-1):
i = j-1
k = j+1
while (i >=0 and k <= n-1):
if (arr[i] + arr[k] < 2*arr[j]):
k = k + 1
elif (arr[i] + arr[k] > 2*arr[j]):
L[i][j] = 2
i -= 1
else:
L[i][j] = L[j][k] + 1
llap = max(llap, L[i][j])
i = i - 1
k = j + 1
while (i >=0):
L[i][j] = 2
i -= 1
return llap
arr = [1,4,5,7,8,10]
print arithmetic(arr)
这会输出 4
。
但是我希望能够找到最多缺少一个值的算术级数。因此,如果 arr = [1,4,5,8,10,13] 我希望它报告长度为 5 的级数,其中缺少一个值。
这能高效地完成吗?
最佳答案
改编 self 对 Longest equally-spaced subsequence 的回答. n
是A
的长度,d
是范围,即最大项减去最小项。
A = [1, 4, 5, 8, 10, 13] # in sorted order
Aset = set(A)
for d in range(1, 13):
already_seen = set()
for a in A:
if a not in already_seen:
b = a
count = 1
while b + d in Aset:
b += d
count += 1
already_seen.add(b)
# if there is a hole to jump over:
if b + 2 * d in Aset:
b += 2 * d
count += 1
while b + d in Aset:
b += d
count += 1
# don't record in already_seen here
print "found %d items in %d .. %d" % (count, a, b)
# collect here the largest 'count'
我相信这个解决方案仍然是 O(n*d)
,尽管在两个嵌套的“for”循环中有两个“while”循环,但它只是具有比没有洞的情况更大的常量。的确,固定一个d
的值:那么我们就在运行n
次的“a”循环中;但是内部两个 while 循环中的每一个在 a
的所有值上总共最多运行 n
次,给出复杂度 O(n+n+n) =又是 O(n)
。
与原始解决方案一样,此解决方案适用于您对绝对最佳答案不感兴趣而只对步长相对较小的子序列 d
的情况:例如n
可能是 1'000'000,但您最多只对 step 的子序列感兴趣 1'000。然后你可以让外循环停止在 1'000。
关于python - 带洞的最长等差数列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18217649/