In python, how does one efficiently find the largest consecutive set of numbers in a list that are not necessarily adjacent?

前端 未结 10 747

For instance, if I have a list

[1,4,2,3,5,4,5,6,7,8,1,3,4,5,9,10,11]

This algorithm should return [1,2,3,4,5,6,7,8,9,10,11].

To cl

相关标签:
10条回答
  • 2020-12-31 11:53

    You need the Maximum contiguous sum(Optimal Substructure):

    def msum2(a):
        bounds, s, t, j = (0,0), -float('infinity'), 0, 0
    
        for i in range(len(a)):
            t = t + a[i]
            if t > s: bounds, s = (j, i+1), t
            if t < 0: t, j = 0, i+1
        return (s, bounds)
    

    This is an example of dynamic programming and is O(N)

    0 讨论(0)
  • 2020-12-31 11:57

    Here is a simple one-pass O(n) solution:

    s = [1,4,2,3,5,4,5,6,7,8,1,3,4,5,9,10,11,42]
    maxrun = -1
    rl = {}
    for x in s:
        run = rl[x] = rl.get(x-1, 0) + 1
        print x-run+1, 'to', x
        if run > maxrun:
            maxend, maxrun = x, run
    print range(maxend-maxrun+1, maxend+1)
    

    The logic may be a little more self-evident if you think in terms of ranges instead of individual variables for the endpoint and run length:

    rl = {}
    best_range = xrange(0)
    for x in s:
        run = rl[x] = rl.get(x-1, 0) + 1
        r = xrange(x-run+1, x+1)
        if len(r) > len(best_range):
            best_range = r
    print list(best_range)
    
    0 讨论(0)
  • 2020-12-31 11:59

    This should do the trick (and is O(n)):

    target = 1
    result = []
    for x in list:
        for y in result:
            if y[0] == target:
                y[0] += 1
                result.append(x)
    

    For any starting number, this works:

    result = []
    for x in mylist:
        matched = False
        for y in result:
            if y[0] == x:
                matched = True
                y[0] += 1
                y.append(x)
        if not matched:
            result.append([x+1, x])
    return max(result, key=len)[1:]
    
    0 讨论(0)
  • 2020-12-31 12:00

    O(n) solution works even if the sequence does not start from the first element.

    Warning does not work if len(A) = 0.

    A = [1,4,2,3,5,4,5,6,7,8,1,3,4,5,9,10,11]
    def pre_process(A): 
        Last = {}
        Arrow = []
        Length = []
        ArgMax = 0
        Max = 0
        for i in xrange(len(A)): 
            Arrow.append(i)
            Length.append(0)  
            if A[i] - 1 in Last: 
                Aux = Last[A[i] - 1]
                Arrow[i] = Aux
                Length[i] = Length[Aux] + 1
            Last[A[i]] = i 
            if Length[i] > Max:
                ArgMax = i 
                Max = Length[i]
        return (Arrow,ArgMax)  
    
    (Arr,Start) = pre_process(A) 
    Old = Arr[Start] 
    ToRev = []
    while 1: 
        ToRev.append(A[Start]) 
        if Old == Start: 
            break
        Start = Old 
        New = Arr[Start]
        Old = New
    ToRev.reverse()
    print ToRev     
    

    Pythonizations are welcome!!

    0 讨论(0)
  • 2020-12-31 12:03

    You can use The Patience Sort implementation of the Largest Ascending Sub-sequence Algorithm

    def LargAscSub(seq):
        deck = []
        for x in seq:
            newDeck = [x]
            i = bisect.bisect_left(deck, newDeck)
            deck[i].insert(0, x) if i != len(deck) else deck.append(newDeck)
        return [p[0] for p in deck]
    

    And here is the Test results

    >>> LargAscSub([1,4,2,3,5,4,5,6,7,8,1,3,4,5,9,10,11])
    [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
    >>> LargAscSub([1, 2, 3, 11, 12, 13, 14])
    [1, 2, 3, 11, 12, 13, 14]
    >>> LargAscSub([11,12,13,14])
    [11, 12, 13, 14]
    

    The Order of Complexity is O(nlogn)

    There was one note in the wiki link where they claimed that you can achieve O(n.loglogn) by relying on Van Emde Boas tree

    0 讨论(0)
  • 2020-12-31 12:09

    Warning: This is the cheaty way to do it (aka I use python...)

    import operator as op
    import itertools as it
    
    def longestSequence(data):
    
        longest = []
    
        for k, g in it.groupby(enumerate(set(data)), lambda(i, y):i-y):
            thisGroup = map(op.itemgetter(1), g)
    
            if len(thisGroup) > len(longest):
                longest = thisGroup
    
        return longest
    
    
    longestSequence([1,4,2,3,5,4,5,6,7,8,1,3,4,5,9,10,11, 15,15,16,17,25])
    
    0 讨论(0)
提交回复
热议问题