【问题标题】:Find longest consecutive sub array (not sorted)-Python查找最长连续子数组(未排序)-Python
【发布时间】:2019-09-15 13:51:48
【问题描述】:

v=[1,2,3,11,5,8,9,10,11,6,4] 在上面的列表中 1,2,3 是连续的数字(第一个连续的集合)。 8,9,10,11 是连续的数字(第二组,最大的一个)。我怎样才能找到这第二套?下面的代码给出了连续的数字:

for i in range(len(v)-1):
    if v[i+1]==v[i]+1:
        if v[i-1]!=v[i]-1:
             print(v[i])
        print(v[i]+1)

Output:1,2,3,8,9,10,11

我正在考虑使用类似下面的东西并将输出添加到新列表中,然后找出列表的最大值。我想不出将这两个想法结合起来的逻辑。

for i in range(len(v)-1):
    for j in range(i+1,len(v)):
        if v[j]-v[i]  

我查看了这个example,但我认为该解决方案与我正在寻找的不同。提前感谢您的时间和建议。

【问题讨论】:

  • 您想要一个在您的尝试中使用这些概念的解决方案,还是任何解决方案?
  • 不是很复杂的东西(如果可能的话,比如 lambdas)。谢谢。

标签: python list


【解决方案1】:

您可以遍历列表并继续将项目附加到可能最长的连续子列表中,如果该项目与子列表的最后一项不连续,则开始一个新的,并将子列表分配为如果新的最长子列表比当前最长的子列表长:

candidate = []
longest = []
for i in v:
    if candidate and candidate[-1] != i - 1:
        if len(candidate) > len(longest):
            longest = candidate
        candidate = []
    candidate.append(i)
if len(candidate) > len(longest):
    longest = candidate

longest 变为:

[8, 9, 10, 11]

【讨论】:

    【解决方案2】:

    你已经很接近了。将当前运行存储为列表,必要时更新最佳列表,并在您中断运行时将其清除。如果最后一个分组出现在列表的最末尾,则应注意将其包括在内。

    v = [1,2,3,11,5,8,9,10,11,6,4]
    best = []
    run = []
    
    for i in range(1, len(v) + 1):
        run.append(v[i-1])
    
        if i == len(v) or v[i-1] + 1 != v[i]:
            if len(best) < len(run):
                best = run
    
            run = []
    
    print(best)
    

    输出:

    [8, 9, 10, 11]
    

    【讨论】:

      【解决方案3】:

      您可以使用sliding window 缩小大小并检查所有数字是否按升序排列:

      from itertools import islice
      
      def window(seq, n=2):
          "Returns a sliding window (of width n) over data from the iterable"
          "   s -> (s0,s1,...s[n-1]), (s1,s2,...,sn), ...                   "
          it = iter(seq)
          result = tuple(islice(it, n))
          if len(result) == n:
              yield result
          for elem in it:
              result = result[1:] + (elem,)
              yield result
      
      
      def longestConsecutiveSeq(s):
        for seq in (window(s, i) for i in range(len(s)-1, 1, -1)):
          for subseq in seq:
            l = list(subseq)
            if all((y-x) == 1 for (x, y) in zip(l, l[1:])):
              return l
      
      print(longestConsecutiveSeq([1,2,3,11,5,8,9,10,11,6,4]))
      

      结果:[8, 9, 10, 11]

      此算法将在第一次遇到最大尺寸时停止。

      【讨论】:

        【解决方案4】:

        你可以使用熊猫:

        import pandas as pd
        
        v=[1,2,3,11,5,8,9,10,11,6,4]
        
        s = pd.Series(v)
        
        sgc = s.groupby(s.diff().ne(1).cumsum()).transform('count')
        
        result = s[sgc == sgc.max()].tolist()
        
        result
        

        输出:

        [8, 9, 10, 11]
        

        详情:

        创建一个pandas系列,使用diff计算与前一个值的差值。接下来,使用ne创建一个差值不等于1的布尔系列,然后cumsum这个布尔系列创建组,其中连续值都分组在一起。使用groupbytransform 来计算每条记录的组大小。最后,使用布尔索引仅选择组中的计数等于所有组的最大计数的系列部分。然后使用tolist 转换为数组。

        【讨论】:

        • 我对 Pandas 不是很熟悉,但是这个解释很好。
        【解决方案5】:

        您可以使用“groupby()”函数利用元素及其索引之间的差异对元素进行分组:

        from itertools import groupby
        
        l = [1, 2, 3, 11, 5, 8, 9, 10, 11, 6, 4]
        
        gb = groupby(enumerate(l), lambda x: x[0] - x[1])
        max(([i for _, i in g] for _, g in gb), key=len)
        # [8, 9, 10, 11]
        

        【讨论】:

          猜你喜欢
          • 2020-09-19
          • 2011-11-19
          • 1970-01-01
          • 2013-09-13
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多