我有这个,它有效:
# 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
但是,我真的很想学好这些东西。 :)'线性'时间是什么意思?
答案 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”是引起所有注意的那个。
最恶劣的算法被分类为“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