什么是O(n)算法按顺序配对两个相等长度的列表?

时间:2012-01-08 07:08:07

标签: python algorithm

假设我在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')]

4 个答案:

答案 0 :(得分:6)

您正在寻找zipsorted内置函数。

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会给你一个恒定的时间(但不到位)元素的配对。来自izipitertools具有恒定的内存占用量,但每次无序访问元素时都需要执行线性时间扫描,然后重置生成器。

如果你能负担得起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')]