给定两个按递增顺序排序的列表,创建并返回一个按排序顺序排列的合并列表。您可以修改传入的列表。理想情况下,解决方案应该在“线性”时间内工作,即对两个列表进行一次遍历。
我想出的解决方案是:
def linear_merge(list1, list2):
list1.extend(list2)
return sorted(list1)
它通过了测试函数,但给出的解决方案是这样的:
def linear_merge(list1, list2):
result = []
# Look at the two lists so long as both are non-empty.
# Take whichever element [0] is smaller.
while len(list1) and len(list2):
if list1[0] < list2[0]:
result.append(list1.pop(0))
else:
result.append(list2.pop(0))
# Now tack on what's left
result.extend(list1)
result.extend(list2)
return result
作为解决方案的一部分,包括以下内容:
注意:上述解决方案很可爱,但是使用标准Python列表实现时,list.pop(0)不是恒定时间,因此上述解决方案不是严格的线性时间。另一种方法使用pop(-1)从每个列表中删除最后一个元素,构建一个反向的解决方案列表。然后使用reversed()将结果放回正确的顺序。该解决方案在线性时间内运行,但更加丑陋。
为什么这两个解决方案如此不同?我有什么遗漏,还是它们过于复杂了?
pop
从列表中移除一个项目并返回其值,因此您正在从每个列表中删除项目并将它们放入result
中。初始循环运行的时间与list1
和list2
都包含任何内容一样长。当其中一个用完时,您只需取出另一个中剩下的任何内容并将其附加到result
上;这就是extend
的作用。 - Tom Zychpop(0)
在标准Python实现中不是以恒定时间运行的,那么你肯定不缺乏思考能力。对于这种情况,尝试从建模问题开始:拿一副牌,洗牌,切成两半,将每半排序,然后将这两半拼在一起进行排序 - 并思考你正在做什么。 - Karl Knechtelpop(0)
问题的另一种简单方法是根本不要从子列表中删除项目,只需通过每个列表推进索引,将引用复制到结果列表中即可。 :) - Karl Knechtel