找到序列中最长的算术级数

时间:2017-04-01 01:46:14

标签: python math sequence

假设我有一个数字递增的序列,我想找到序列中最长算术级数的长度。最长的算术级数意味着具有共同差异的递增序列,例如[2,4,6,8]或[3,6,9,12]。

例如, 对于[5, 10, 14, 15, 17][5, 10, 15]是最长的算术级数,长度为3;

对于[10, 12, 13, 20, 22, 23, 30]

[10, 20, 30]是长度为3的最长算术级数;

[7, 10, 12, 13, 15, 20, 21]

[10, 15, 20][7, 10, 13]是长度为3的最长算术进度。

这个网站 https://prismoskills.appspot.com/lessons/Dynamic_Programming/Chapter_22_-_Longest_arithmetic_progression.jsp 提供了对问题的一些见解,即通过循环j并考虑 每3个元素。我打算在Python中使用这个算法,我的代码如下:

def length_of_AP(L):
n = len(L)
Table = [[0 for _ in range(n)] for _ in range(n)]
length_of_AP = 2

# initialise the last column of the table as all i and (n-1) pairs have lenth 2
for i in range(n):
        Table[i][n-1] =2

# loop around the list and i, k such that L[i] + L[k] = 2 * L[j]
for j in range(n - 2, 0, -1):
        i = j - 1
        k = j + 1
        while i >= 0 and k < n:
                difference = (L[i] + L[k]) - 2 * L[j]
                if difference < 0:
                        k = k + 1
                else:
                        if difference > 0:
                                i = i - 1
                        else:
                                Table[i][j] = Table[j][k] + 1
                                length_of_AP = max(length_of_AP, Table[i][j])
                                k = k + 1
                                i = i - 1
return length_of_AP

此功能适用于[1,3,4,5,7,8,9],但它不适用于[5,10,14,15,20,25,26,27, 28,30,31],我应该得到6但我得到4.我可以看到原因是列表中的25,26,27,28可能是我的功能分散注意力的因素。如何更改我的功能,以便为我提供所需的结果。

任何帮助都可能会受到赞赏。

2 个答案:

答案 0 :(得分:0)

你试过吗? 这是一个快速强力实施,对于小型数据集,它应该足够快地运行:

def gen(seq):
    diff = ((b-a, a) for a, b in it.combinations(sorted(seq), 2))
    for d, n in diff:
        k = []
        while n in seq:
            k.append(n)
            n += d
        yield (d, k)

def arith(seq):
    return max(gen(seq), key=lambda x: len(x[1]))

In [1]: arith([7, 10, 12, 13, 15, 20, 21])
Out[1]: (3, [7, 10, 13])
In [2]: %timeit arith([7, 10, 12, 13, 15, 20, 21])
10000 loops, best of 3: 23.6 µs per loop
In [3]: seq = {random.randrange(1000) for _ in range(100)}
In [4]: arith(seq)
Out[4]: (171, [229, 400, 571, 742, 913])
In [5]: %timeit arith(seq)
100 loops, best of 3: 3.79 ms per loop
In [6]: seq = {random.randrange(1000000) for _ in range(1000)}
In [7]: arith(seq)
Out[7]: (81261, [821349, 902610, 983871])
In [8]: %timeit arith(seq)
1 loop, best of 3: 434 ms per loop

答案 1 :(得分:0)

按照链接并运行第二个示例,看起来代码实际上找到了正确的LAP

  

5,10,15,20,25,30,

但找不到合适的长度。我没有花太多时间分析代码而是分析

    // Any 2-letter series is an AP
    // Here we initialize only for the last column of lookup because
    // all i and (n-1) pairs form an AP of size 2  
    for (int i=0; i<n; i++)
        lookup[i][n-1] = 2;

对我来说很可疑。您似乎需要使用2而不是最后一列初始化整个 lookup表,如果我这样做,它也会开始在您的示例上获得正确的长度。

所以摆脱&#34;初始化&#34;循环并将第3行更改为以下代码:

# initialise whole table with 2 as all (i, j) pairs have length 2    
Table = [[2 for _ in range(n)] for _ in range(n)]

而且他们的

  

样品执行:
  最大AP长度= 6
  3,5,7,9,11,13,15,17,

也包含这个错误,实际上只是因为运气好而打印出正确的序列。如果我将sortedArr修改为

int sortedArr[] = new int[] {3, 4, 5, 7, 8, 9, 11, 13, 14, 15, 16, 17, 18,  112, 113, 114, 115, 116, 117, 118};

我得到以下输出

  

最大AP长度= 7
  112,113,114,115,116,117,118,

这显然是错误的,因为原始的8项长序列3, 5, 7, 9, 11, 13, 15, 17,仍在那里。