计算列表中的所有序列

时间:2017-09-10 22:37:50

标签: python dynamic-programming

我的自学任务是查找列表中有多少序列。序列是一组数字,每个数字比前一个大1。所以,在列表中:  [1,2,3,5,8,10,12,13,14,15,17,19,21,23,24,25,26]有3个序列:1,2,3; 12,13,14,15; 23,24,25,26。

我花了几个小时才得到一个解决方案,我认为这是一种解决方法,而不是真正的解决方案。

我的解决方案是有一个单独的列表来添加序列并计算更新此列表的尝试。我计算了第一个追加,以及除已经存在的序列之外的每个新追加。

我相信有一个没有额外列表的解决方案,它允许计算序列本身而不是列表操作尝试。

numbers = [1,2,3,5,8,10,12,13,14,15,17,19,21,23,24,25,26]

goods = []
count = 0

for i in range(len(numbers)-1):
    if numbers[i] + 1 == numbers[i+1]:

        if goods == []:
            goods.append(numbers[i])
            count = count + 1

        elif numbers[i] != goods[-1]:
            goods.append(numbers[i])
            count = count + 1

        if numbers[i+1] != goods[-1]:
            goods.append(numbers[i+1])

我的调试输出:

Number 1 added to: [1]
First count change: 1

Number 12 added to: [1, 2, 3, 12]
Normal count change: 2

Number 23 added to: [1, 2, 3, 12, 13, 14, 15, 23]
Normal count change: 3

4 个答案:

答案 0 :(得分:1)

一种方法是迭代成对元素:

l = [1,2,3,5,8,10,12,13,14,15,17,19,21,23,24,25,26]

res = [[]]
for item1, item2 in zip(l, l[1:]):  # pairwise iteration
    if item2 - item1 == 1:
        # The difference is 1, if we're at the beginning of a sequence add both
        # to the result, otherwise just the second one (the first one is already
        # included because of the previous iteration).
        if not res[-1]:  # index -1 means "last element".
            res[-1].extend((item1, item2))
        else:
            res[-1].append(item2)
    elif res[-1]: 
        # The difference isn't 1 so add a new empty list in case it just ended a sequence.
        res.append([])

# In case "l" doesn't end with a "sequence" one needs to remove the trailing empty list.
if not res[-1]:
    del res[-1]

>>> res
[[1, 2, 3], [12, 13, 14, 15], [23, 24, 25, 26]]

>>> len(res)  # the amount of these sequences
3

与上述方法相比,没有zip的解决方案只需要很小的更改(循环和循环的开头):

l = [1,2,3,5,8,10,12,13,14,15,17,19,21,23,24,25,26]

res = [[]]
for idx in range(1, len(l)):
    item1 = l[idx-1]
    item2 = l[idx]
    if item2 - item1 == 1:
        if not res[-1]:
            res[-1].extend((item1, item2))
        else:
            res[-1].append(item2)
    elif res[-1]: 
        res.append([])
if not res[-1]:
    del res[-1]

答案 1 :(得分:1)

这可以通过动态编程来解决。如果您只想知道序列的数量,并且实际上不需要知道序列是什么,那么您应该只使用几个变量来完成此操作。实际上,当你浏览列表时,你真的只需要知道你当前是否在一个序列中,如果不是,如果下一个增加1则使其成为一个序列的开头,如果是,那么下一个序列的大于1使它成为序列的出口。之后,您只需要确保在列表结尾之前结束循环一个单元格,因为最后一个单元格不能单独形成一个序列,因此在执行检查时不会导致错误。以下是示例代码

isSeq=false

for i in range(len(numbers)-1):
    if isSeq==false:
       if numbers[i]+1==numbers[i+1]:
           isSeq=true  
           count=count+1
    elif 
       if numbers[i]+1!=numbers[i+1]:
           isSeq=false              

这是动态编程教程的链接。

https://www.codechef.com/wiki/tutorial-dynamic-programming

答案 2 :(得分:1)

感谢大家的帮助!

Legman建议原始解决方案在我在本文中结束另一个解决方案之前未能实现。

MSeifert帮助找到了正确的列表:

CALCULATE(
    SUM(Tonnes),
    Filter(Query,[Deliveryid]=[Deliveryid])
    )

答案 3 :(得分:0)

取自python itertools文档,如图所示here,您可以使用itemgettergroupby仅使用一个列表来执行此操作,如下所示:

>>> from itertools import groupby
>>> from operator import itemgetter
>>>
>>> l = [1, 2, 3, 5, 8, 10, 12, 13, 14, 15, 17, 19, 21, 23, 24, 25, 26]
>>>
>>> counter = 0
>>> for k, g in groupby(enumerate(l), lambda (i,x):i-x):
...     seq = map(itemgetter(1), g)
...     if len(seq)>1:
...         print seq
...         counter+=1
...
[1, 2, 3]
[12, 13, 14, 15]
[23, 24, 25, 26]
>>> counter
3

注意:正如@MSeifert所正确提到的,签名中的元组解包只能在Python 2中解析,并且在Python 3上会失败 - 所以这是一个python 2.x解决方案。 / p>