给定列表中最长的减少子列表

时间:2016-10-31 06:28:18

标签: python list sequence

我想在给定列表中找到最长的递减子序列,例如L = [1,2,1,2,1,2,1,2,1],结果应为[2,1]但是我似乎无法产生这样的结果。有人能告诉我为什么它不起作用?输出是[0,2,1,2,1,2,1,2,1],没关系第一个零,但结果应该产生[2,1]。

这是我试过的代码

L = [1, 2, 1, 2, 1, 2, 1, 2, 1]

current = [0]
smallest = []

for i in  range(len(L)):
    if i < (len(L)-1):
        if L[i] >= L[i+1]:
            current.append(L[i])

        else :    
            if L[i] < current[-1]:
                current.append(L[i])

    elif i>= (len(L)-1):
        if L[-1]<L[i-1]:
            current.append(L[i])
    else:
        current = [i]
    if len(current) > len(smallest):
            smallest = current

结果:[0,2,1,2,1,2,1,2,1]

期望的结果:[2,1]

3 个答案:

答案 0 :(得分:2)

有很多方法可以解决这个问题。在Py3中 - 使用itertools.accumulate进行动态编程:

>>> import operator as op
>>> import itertools as it
>>> L = [1, 2, 1, 2, 1, 2, 1, 2, 1]
>>> dyn = it.accumulate(it.chain([0], zip(L, L[1:])), lambda x, y: (x+1)*(y[0]>y[1]))
>>> i, l = max(enumerate(dyn), key=op.itemgetter(1))
>>> L[i-l:i+1]
[2, 1]

答案 1 :(得分:1)

当您说current = [0]时,它实际上会将0添加到列表中,也许您想要current = [L[0]]
见:

def longest_decreasing_sublist(a):
  lds, current = [], [a[0]]
  for val in a[1:]:
    if val < current[-1]: current.append(val)
    else:
      lds = current[:] if len(current) > len(lds) else lds
      current = [val]
  lds = current[:] if len(current) > len(lds) else lds
  return lds

L = [1, 2, 1, 2, 1, 2, 1, 2, 1]
print (longest_decreasing_sublist(L))
# [2, 1]

答案 2 :(得分:0)

您最好先预先设计代码的可维护性和可读性,这样您就可以轻松地单独测试软件的组件,而不是试图一次性解决整个问题。这被称为功能分解。

考虑最顶层的需求。

首先,您需要一种方法在数组中的给定点获取最长的递减子集,以便您可以智能地比较各种序列。

您可以使用以下代码执行此操作:

def getNextSequence(myList, index):
    # Beyond list end, return empty list.

    if index > len(myList):
        return []

    # Construct initial list, keep adding until either
    # an increase is found or no elements left.

    sequence = [ myList[index] ]
    addIdx = index + 1
    while addIdx < len(myList) and myList[addIdx] <= myList[addIdx - 1]:
        sequence.append(myList[addIdx])
        addIdx += 1

    # And there you have it, the sequence at a given point.

    return sequence

其次,您需要能够存储当前最长的一个并检查长度以查看当前的长度是否大于迄今为止最长的那个。

分解为:

def getLongestSequence(myList):
    # Initially no sequence, even a sequence of one
    # will beat this.

    longestSequence = []

    # This index is where we are checking. Keep checking
    # until all possibilities exhausted.

    checkIndex = 0
    while checkIndex < len(myList):
        # Get current sequence, save it if it's longer
        # than the currently longest one.

        currentSequence = getNextSequence(myList, index)
        if len(currentSequence) > len(longestSequence):
            longestSequence = currentSequence

        # Adjust index to next checking point.

        checkIndex += len(currentSequence)

    # All done, just return the longest sequence.

    return longestSequence

那里重要的是(除了可读性之外)当然是指数的变化。一旦你建立了一个递减序列,你永远不会需要查看它内部的任何地方,因为其中的任何部分序列自然会比整体更短。

换句话说,如果您有8, 7, 6, 5, 9,则从7 开始的序列<(em)不能(按照定义)长于从8开始的序列。因此,您可以直接跳至9