查找列表中最长的连续数字范围

时间:2019-04-10 15:24:07

标签: python list

我有以下数字列表:

numbers = numbers = [  1, 3, 11,  12,  14,  15,  16, 3, 4, 6]

我想获取最长连续数字范围的开始和结束索引。连续范围是指不跳过的整数范围,即1,2,3,4,5 ...

这是我的方法:

def get_longest_consecutive_numbers(numbers):

    # 1. Split the numbers list into sublists of consecutive numbers
    split_list = []
    j = 0
    for i in range(1,len(numbers)-1):
        if numbers[i]+1 is not numbers[i+1]:
            split_list.append(numbers[j:i])
            j = i

    # 2. Find index of longest sublist (of consecutive numbers)
    longest_sublist_index = max((len(l), i) for i, l in enumerate(split_list))[1]

    # 3. Concatenate all sublists up to this index back together
    rest = split_list[:longest_sublist_index]
    concat_list = [j for i in rest for j in i]

    # 4. 
    # Start Index: Length of concatenated list
    # End Index: Start Index + Length of longest sublist in split_list

    start_index = len(concat_list)
    end_index = start_index + len(split_list[longest_sublist_index])

    return start_index, end_index

如果我将函数应用于数字列表:

 get_longest_consecutive_numbers(numbers)

我得到:

(3, 6)

这是正确的...但是...

我想知道是否还有一种更简单(更好)的方法?

5 个答案:

答案 0 :(得分:2)

您还可以对其使用递归:

numbers = [1, 3, 11,  12,  14,  15,  16, 3, 4, 6]

def getMaxConsecutiveInd(index):
    if numbers[index] + 1 == numbers[index + 1]:
        # call the functions if values are cosecutive to check next value
        return getMaxConsecutiveInd(index + 1)
    # return last index for cosecutive numbers
    return index


max_length, start_index, end_index = 0,0,0

i = 0
while i < len(numbers) - 1:
    con_index = getMaxConsecutiveInd(i)
    # if available max_length is less than new_max_length(con_index - i)
    # then change start_index and end_index  
    if max_length < con_index - i:
        max_length = con_index - i
        start_index = i
        end_index = con_index
    # change value of i to latest con_index if i != con_index
    if i == con_index:
        i = i + 1
    else:
        i = con_index

print(start_index, end_index, max_length)
Output: (4,6,2)

numbers = [1, 2, 3, 4, 5, 6, 7, 11, 12, 14, 15, 16, 17, 18, 3, 4, 6]
Output: (0,6,6)


答案 1 :(得分:1)

如何使用2指针方法:

  • 设置开始= 0,结束= 0
  • 设置bestLen = 1,bestStart = 0
  • while结束
  • 如果数字[end] + 1 ==数字[end + 1],则增加end;设置bestLen = max(bestLen,end-start)(如果刚刚更新了bestLen,还设置了bestStart =开始)
  • 其他增加结束;设置开始=结束
  • 返回范围[bestStart ... bestStart + bestLen]
  • 您将获得O(n)时间和O(1)额外空间。

    答案 2 :(得分:1)

    让我们玩得开心:

    1. 创建包含列表的范围

    2. 列表与列表的对称差异

    3. 计算以下两个数字之间的最大距离(为您提供最大长度)

    4. 获取起点和终点的索引

    这是代码:

    def longest_weird(numbers):
        delta = list(set(range(max(numbers))).symmetric_difference(numbers))
        start,end = 0,0
        maxi = 0
        for i,x in enumerate(delta[:-1]):
            aux = max(maxi,delta[i+1]-x)
            if aux != maxi:
                start,end = (x+1,delta[i+1]-1)
                maxi = aux
        return numbers.index(start),numbers.index(end)
    

    答案 3 :(得分:1)

    numbers = [  1, 3, 11,  12,  14,  15,  16, 3, 4, 6]
    
    def longest(numbers):
        max, count_ = 1, 1
        start_idx, end_idx = 0, 0
        for i in range(len(numbers)-1):
            # if difference between number and his follower is 1,they are in sequence
            if numbers[i+1]-numbers[i] ==1:
                count_ = count_+1
            else:
                if count_ > max :
                    max = count_
                    end_idx = i
                    start_idx = i+1 - max
                # Reset counter
                count_ = 1
        return (start_idx,end_idx,max)
    
    
    print (longest(numbers))
    

    输出:

    (4, 6, 3) #start_idx, end_idx, len
    

    答案 4 :(得分:1)

    您可以使用numpy.diff来计算列表中连续元素之间的差异,然后使用itertools.groupby来收集差异等于1的元素。

    import numpy as np
    from itertools import groupby
    from operator import itemgetter
    
    def get_longest_consecutive_numbers(numbers):
        idx = max(
            (
                list(map(itemgetter(0), g)) 
                for i, g in groupby(enumerate(np.diff(numbers)==1), itemgetter(1)) 
                if i
            ), 
            key=len
        )
        return (idx[0], idx[-1]+1)
    
    print(get_longest_consecutive_numbers(numbers))
    #(4,6)