My implementation of merging two sorted lists in linear time - what could be improved?

后端 未结 9 547
忘掉有多难
忘掉有多难 2021-01-01 04:47

Fromg Google\'s Python Class:

E. Given two lists sorted in increasing order, create and return a merged
list of all the elements in sorted order. You may mod         


        
相关标签:
9条回答
  • 2021-01-01 05:08

    This solution runs in linear time and without editing l1 and l2:

    def merge(l1, l2):
      m, m2 = len(l1), len(l2)
      newList = []
      l, r = 0, 0
      while l < m and r < m2:
        if l1[l] < l2[r]:
          newList.append(l1[l])
          l += 1
        else:
          newList.append(l2[r])
          r += 1
      return newList + l1[l:] + l2[r:]
    
    0 讨论(0)
  • 2021-01-01 05:14

    According to a note here:

    # Note: the solution above is kind of cute, but unforunately list.pop(0)
    # is not constant time with the standard python list implementation, so
    # the above is not strictly linear time.
    # An alternate approach uses pop(-1) to remove the endmost elements
    # from each list, building a solution list which is backwards.
    # Then use reversed() to put the result back in the correct order. That
    # solution works in linear time, but is more ugly.    
    

    and this link http://www.ics.uci.edu/~pattis/ICS-33/lectures/complexitypython.txt

    append is O(1), reverse is O(n) but then it also says that pop is O(n) so which is which? Anyway I have modified the accepted answer to use pop(-1):

    def linear_merge(list1, list2):
        # +++your code here+++
        ret = []
        while list1 and list2:
            if list1[-1] > list2[-1]:
                ret.append(list1.pop(-1))
            else:
                ret.append(list2.pop(-1))
    
        ret.reverse()
    
        return list1 + list2 + ret
    
    0 讨论(0)
  • 2021-01-01 05:15

    Why stop at two lists?

    Here's my generator based implementation to merge any number of sorted iterators in linear time.

    I'm not sure why something like this isn't in itertools...

    def merge(*sortedlists):
    
        # Create a list of tuples containing each iterator and its first value
        iterlist = [[i,i.next()] for i in [iter(j) for j in sortedlists]]
    
        # Perform an initial sort of each iterator's first value
        iterlist.sort(key=lambda x: x[1])
    
        # Helper function to move the larger first item to its proper position
        def reorder(iterlist, i): 
            if i == len(iterlist) or iterlist[0][1] < iterlist[i][1]:
                iterlist.insert(i-1,iterlist.pop(0))
            else:
                reorder(iterlist,i+1)
    
        while True:
            if len(iterlist):
                # Reorder the list if the 1st element has grown larger than the 2nd
                if len(iterlist) > 1 and iterlist[0][1] > iterlist[1][1]:
                    reorder(iterlist, 1)
    
                yield iterlist[0][1]
    
                # try to pull the next value from the current iterator
                try:
                    iterlist[0][1] = iterlist[0][0].next()
                except StopIteration:
                    del iterlist[0]
            else:
                break
    

    Here's an example:

    x = [1,10,20,33,99]
    y = [3,11,20,99,1001]
    z = [3,5,7,70,1002]
    
    [i for i in merge(x,y,z)]
    
    0 讨论(0)
提交回复
热议问题