假设我在Python中有两个相等长度的无序列表:
a = [5, 2, 3, 1, 4]
b = ['d', 'b', 'a', 'c', 'e']
是否有O(n)就地算法来获得以下结果?
[(1, 'a'), (2, 'b'), (3, 'c'), (4, 'd'), (5, 'e')]
答案 0 :(得分:6)
r = zip(sorted(a), sorted(b))
zip
需要两个迭代并按顺序将它们组合在一起(因此如果列表未排序,则会得到(5, 'd')
作为第一个元组),并且任何多余的值似乎都被截断/忽略(因为它们不能配对)。
sorted
,我上次查看代码库时,根据您给出的列表大小使用不同的排序算法 - 它应该在大约O(n * log(n))处执行。 没有实用的排序可以提供O(n)性能,因为您还必须将单个值与某些金额中的其余值进行比较时间。
如果要进行就地排序,可以使用list.sort()
函数,该函数执行就地排序。这会将语法更改为以下内容:
a.sort()
b.sort()
r = zip(a, b)
答案 1 :(得分:2)
我认为没有。
sort()
被认为是O(nlogn)
,你的要求不仅仅是排序(尽管只是一点点)。如果对此有某种O(n)
算法,我们也可以使用它来替换已经研究了很长时间并且不太可能有sort()
算法的O(n)
。
答案 2 :(得分:2)
zip
会给你一个恒定的时间(但不到位)元素的配对。来自izip
的itertools
具有恒定的内存占用量,但每次无序访问元素时都需要执行线性时间扫描,然后重置生成器。
如果你能负担得起O(n log(n))就地排序算法,那么关于sort()
here的默认实现有一个很好的问题和答案。
我认为大多数应用程序的最佳方法是列表足够大,以便内存和计算时间很重要,就是在每个数组上调用sort
,然后使用itertools.izip
方法创建一个发电机上的结果。这种方法具有恒定的内存开销,并且与通用阵列上的渐近计算时间一样好。
可以使用 radix sort 或某些变体进行常量时间排序,但是这不存在并对您的数据类型做出一些假设(即,int或chars数组有效,但浮点数和BigInts变得混乱)
侧栏:如果此社区中的任何人有空闲时间,维基百科上的桶排序文章需要引起注意。
答案 3 :(得分:1)
是的,当排序小于或等于N的正整数时,有一种方法可以得到O(N)。 这样做的方法是使用桶。 这是一个实现:
def _sort(_list):
buckets=[0]*len(_list)
for i in _list:
i=int(i)
assert(0<=i<len(_list))
buckets[i]+=1
result=[]
for num,count in enumerate(buckets):
result.extend([num]*count)
return result
alp=map(ord,list("dabce"))
m=min(alp)
alp=[i-m for i in alp]
alp=_sort(alp)
alp=[i+m for i in alp]
alp=map(chr,alp)
print zip(_sort([1,3,2,0,4]),alp)
#[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (4, 'e')]