【问题标题】:Identify groups of continuous numbers from consecutive list in python从python中的连续列表中识别连续数字组
【发布时间】:2016-08-26 20:42:25
【问题描述】:

python 中从 n 个连续列表中选取多个 n 个连续整数的最有效方法是什么,从每个列表中选取一个整数。这里的 n 相当大..比如说 100 秒左右。

L1 = [5,3,2,7,1]
L2 = [3,5,6,8,9,21,2]
L3 = [5,3,6,7,3,9]

我想从连续列表中打印出连续整数的范围,其中第一个元素是从第一个列表中提取的,第二个元素是从第二个列表中提取的,依此类推:

Candidate solution [5,6,7], [1,2,3], [7,8,9]

【问题讨论】:

  • 所以你想要每个列表中最大的连续范围,但不考虑当前的顺序?一个列表中可以有多个等长的范围吗?如果有,如何处理?
  • @ByteCommander 不不不。你完全错了。我不希望每个列表中都有最大的连续范围。我希望从连续列表中提取连续元素,而不是在列表中。希望我说清楚了。
  • 啊,所以你有 3 个列表并通过从每个列表中选择一个数字来形成长度为 3 的连续范围?列表的数量总是 3 还是可以变化的?
  • @AKS 我尝试对每个列表进行排序,然后选择每个列表中的每个元素并检查它们是否是连续整数,但最坏的情况复杂度可能是 O(l1*l2*l3),其中 l1,l2 和 l3 是列表 L1,L2,L3 的长度。如果我有 100 个这样的列表,那么性能将会受到影响。
  • @ByteCommander 你做对了。列表的数量可以变化,通常在 100 的范围内。

标签: python algorithm list range continuous


【解决方案1】:
L1 = [5,3,2,7,1]
L2 = [3,5,6,8,9,21,2]
L3 = [5,3,6,7,3,9]
cons_l = []
L = [L2] + [L3] #+[L4] #+ ...+ ..... ### Add any number of list here..

j = 0
for l1 in L1:
   cons_l.append([])
   cons_l[j].append(l1)
   for l in range(0, len(L)):
      if l1+l+1 in L[l]:
         cons_l[j].append(l1+l+1)
      else:
         del cons_l[j]
         j -= 1
         break
   j += 1
print cons_l

【讨论】:

  • 如果假设我有 100 个列表而不是 3 个列表..那么您将如何扩展您的算法.?
  • @rombi,请看代码。我进行了一些更改以提供动态列表的解决方案(最多 n 个)。
【解决方案2】:

我会先尝试使用高效的排序算法对列表进行排序。您可以尝试Bubble Sort,但其他排序算法也可能有效。

然后您可以遍历 1-n 的整数并在字符串中查找连续的整数范围。这样,您最多可以进行 n² 次排序操作和 n 次“查找”操作。

这对你来说够快吗?

【讨论】:

  • 嗯,很好。保存以备后用。
  • @Harper 如何进行查找操作。列表的长度不固定。
  • 是的,看来我像@ByteCommander 一样解释了这个问题。另外,您已经尝试过排序,但它太慢了,所以我撤回了我的答案;-)
【解决方案3】:

您可以使用列表推导

In [23]: ls = [[5,3,2,7,1],[3,5,6,8,9,21,2],[5,3,6,7,3,9],]

In [24]: l = len(ls)

In [25]: [list(range(s,s+l)) for s in ls[0] if all(i in l for i,l in zip(range(s+1,s+l),ls[1:]))]
Out[25]: [[5, 6, 7], [7, 8, 9], [1, 2, 3]]

它的阵风是,对于第一个列表中的每个数字生成一个递增数字序列,并检查每个数字是否包含在剩余列表序列中的相应列表中。

请注意,all 在不满足条件时立即停止迭代生成器表达式,从而提高方法的效率。

对于问题的 LARGE 实例,可能值得在列表理解之前将所有列表转换为集合,ls = [set(l) for l in ls]


附录

使用for 循环和条件语句的不带列表理解的变体,请注意,在搜索序列之前,内部列表已转换为集合。

ls = [[5, 3, 2, 7, 1], [3, 5, 6, 8, 9, 21, 2], [5, 3, 6, 7, 3, 9]]
l = len(ls)
ls = [set(li) for li in ls]

candidates = []
for n in ls[0]:
    if all(i in l for i, l in zip(range(n+1, n+l), ls[1:])):
        candidates.append(list(range(n, n+l)))

【讨论】:

    【解决方案4】:

    也许使用集合对您的应用程序来说已经足够快了?有点暴力,但如果我理解正确,它符合您的限制:

    lists = [
      [5,3,2,7,1],
      [3,5,6,8,9,21,2],
      [5,3,6,7,3,9],
    ]
    
    candidates = list()
    
    # Without the first one
    rest_of_sets = [set(l) for l in lists[1:]]
    
    for fe in lists[0]:
        skip_partial = False
        for i, s in enumerate(rest_of_sets, 1):
            if fe + i not in s:
                skip_partial = True
                break
        if not skip_partial:
            candidates.append(range(fe, fe+len(sets)))
    
    print candidates
    

    【讨论】:

      猜你喜欢
      • 2011-01-10
      • 1970-01-01
      • 2020-11-12
      • 2021-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多