如何合并两个列表并按“线性”时间对它们进行排序?

时间:2010-03-21 21:55:15

标签: python list merge

我有这个,它有效:

# E. Given two lists sorted in increasing order, create and return a merged
# list of all the elements in sorted order. You may modify the passed in lists.
# Ideally, the solution should work in "linear" time, making a single
# pass of both lists.
def linear_merge(list1, list2):
  finalList = []
  for item in list1:
    finalList.append(item)
  for item in list2:
    finalList.append(item)
  finalList.sort()
  return finalList
  # +++your code here+++
  return

但是,我真的很想学好这些东西。 :)'线性'时间是什么意思?

9 个答案:

答案 0 :(得分:6)

线性表示Big O notation中的O(n),而您的代码使用的sort()很可能是O(nlogn)

问题是要求standard merge algorithm。一个简单的Python实现是:

def merge(l, m):
    result = []
    i = j = 0
    total = len(l) + len(m)
    while len(result) != total:
        if len(l) == i:
            result += m[j:]
            break
        elif len(m) == j:
            result += l[i:]
            break
        elif l[i] < m[j]:
            result.append(l[i])
            i += 1
        else:
            result.append(m[j])
            j += 1
    return result

>>> merge([1,2,6,7], [1,3,5,9])
[1, 1, 2, 3, 5, 6, 7, 9]

答案 1 :(得分:6)

线性时间意味着所花费的时间受某些未定义的常量时间(在此上下文中)的限制,即您要合并的两个列表中的项目数。你的方法没有实现这一点 - 它需要O(n log n)时间。

当指定算法在问题大小方面花费多长时间时,我们会忽略机器运行速度等细节,这基本上意味着我们忽略所有常量项。我们使用“渐近符号”。这些基本上描述了曲线的形状,您将在x中的问题大小与y中所用时间的图形中绘制。逻辑是如果问题足够大,那么糟糕的曲线(快速变得陡峭的曲线)将总是导致执行时间变慢。在一个非常小的问题上可能会更快(取决于常数,这可能取决于机器),但对于小问题,执行时间通常不是一个大问题。

“大O”指定执行时间的上限。平均执行时间和下限有相关的符号,但“大O”是引起所有注意的那个。

  • O(1)是恒定时间 - 问题大小无关紧要。
  • O(log n)是一条非常浅的曲线 - 随着问题变大,时间会略微增加。
  • O(n)是线性时间 - 每单位增加意味着需要大致恒定的额外时间。该图(大致)是一条直线。
  • 随着问题变得越来越复杂,
  • O(n log n)向上弯曲得越来越陡峭,但并非如此。这是通用排序算法可以做到的最好的。
  • 随着问题变得更加复杂,
  • O(n平方)向上弯曲得更陡峭。这对于像冒泡排序这样的较慢排序算法来说是典型的。

最恶劣的算法被分类为“np-hard”或“np-complete”,其中“np”表示“非多项式” - 曲线比任何多项式更快。指数时间很糟糕,但有些甚至更糟。这些事情仍然存在,但仅限于非常小的问题。

编辑最后一段错误,如评论所示。我的算法理论确实有一些漏洞,很明显我是时候检查了我想到的东西。与此同时,我不太确定如何纠正该段落,所以请加以警告。

对于合并问题,请考虑您的两个输入列表已经排序。输出中的最小项目必须是您输入中的最小项目。从两者中获取第一项并比较两者,并将最小值放在输出中。把最大的背部放在它的来源。你已经完成了一定数量的工作并处理了一个项目。重复,直到两个列表都用尽。

一些细节......首先,将项目放回列表只是为了将其重新拉出来显然是愚蠢的,但它使解释更容易。接下来 - 一个输入列表将在另一个输入列表之前耗尽,因此您需要处理它(基本上只清空其他列表的其余部分并将其添加到输出中)。最后 - 你实际上不必从输入列表中删除项目 - 再次,这只是解释。你可以直接介绍它们。

答案 2 :(得分:3)

Linear time表示程序的运行时与输入的长度成比例。在这种情况下,输入包含两个列表。如果列表的长度是两倍,那么程序将运行大约两倍的时间。从技术上讲,我们说算法应该是O(n),其中 n 是输入的大小(在这种情况下是两个输入列表的长度组合)。

这似乎是作业,所以我不会给你一个答案。虽然这不是作业,但我认为你最好用笔和一笔一张纸,构建两个分类的小样本列表,并弄清楚将如何合并这两个列表。一旦你明白了,实现算法就是小菜一碟。

(如果一切顺利,你会注意到你只需要在一个方向上迭代每个列表一次。这意味着算法确实是线性的。祝你好运!)

答案 3 :(得分:3)

如果以反向排序顺序构建结果,则可以使用pop()并仍为O(N)
列表右端的pop()不需要移动元素,因此是O(1)
在我们返回之前反转列表是O(N)

>>> def merge(l, r):
...     result = []
...     while l and r:
...         if l[-1] > r[-1]:
...             result.append(l.pop())
...         else:
...             result.append(r.pop())
...     result+=(l+r)[::-1]
...     result.reverse()
...     return result
... 
>>> merge([1,2,6,7], [1,3,5,9])
[1, 1, 2, 3, 5, 6, 7, 9]

答案 4 :(得分:2)

该线程包含线性时间合并算法的各种实现。请注意,出于实际目的,您可以使用heapq.merge

答案 5 :(得分:0)

线性时间意味着O(n)复杂度。您可以在此处阅读有关algorithmn comlexity和big-O表示法的内容:http://en.wikipedia.org/wiki/Big_O_notation。 您应该尝试将这些列表组合在一起,而不是在finalList中获取它们之后,尝试逐渐合并它们 - 添加一个元素,确保对结果进行排序,然后添加下一个元素......这应该会给你一些想法。

答案 6 :(得分:0)

一个更简单的版本,需要相同大小的列表:

def merge_sort(L1, L2):
   res = [] 
   for i in range(len(L1)):
      if(L1[i]<L2[i]):
          first = L1[i]  
          secound = L2[i] 
      else:
          first = L2[i]  
          secound = L1[i]  
      res.extend([first,secound]) 
   return res

答案 7 :(得分:0)

itertoolz 提供了一个有效的实现来合并两个排序列表 https://toolz.readthedocs.io/en/latest/_modules/toolz/itertoolz.html#merge_sorted

答案 8 :(得分:-1)

'Linear time'表示时间是O(n)函数,其中n - 输入的项目数(列表中的项目)。
f(n)= O(n)意味着存在常数x和y,使得x * n <= f(n)<= y * n。

def linear_merge(list1, list2):
  finalList = []
  i = 0
  j = 0
  while i < len(list1):
    if j < len(list2):
      if list1[i] < list2[j]:
        finalList.append(list1[i])
        i += 1
      else:
        finalList.append(list2[j])
        j += 1
    else:
      finalList.append(list1[i])
      i += 1
  while j < len(list2):
    finalList.append(list2[j])
    j += 1
  return finalList