有没有比Python中的list.sort()更有效的排序列表的方法?

时间:2014-02-16 11:55:27

标签: python sorting

我正在尝试解决Codechef.com上的挑战,以便在特定时间限制内对大型列表进行排序。我已经尝试使用内置list.sort()和我自己的函数,但是当我上传代码时,它总是显示“超出时间限制”。在运行时方面比使用list.sort()更有效吗?

问题:

  • 根据数字列表,您要按非递减顺序对它们进行排序。
  • 输入
    • t - 列表中的数字的数量,然后t行遵循[t <= 10 ^ 6]。
    • 每行包含一个整数:N [0 <= N <= 10 ^ 6]
  • 输出
    • 以非递减顺序输出给定数字。

我的回答:

test_cases = int(input())
store = []
count = 0
while count < test_cases:
    i = int(input())
    store.append(i)
    count += 1
store.sort()
for each_item in store:
    print(each_item)

2 个答案:

答案 0 :(得分:1)

理论

实际上由于数据限制(最大值10 ^ 6的整数),最有效的是使用计数排序(桶排序),因为它的线性复杂性,而不是sorted.sort(O(nlogn))

显然,对于大量数字(类似的数量级)来说确实如此。如果t 小于最大值,那么(根据经验)使用O(nlogn)方法会更好。

所以:

  • 从复杂的角度来看:最好使用count sort,即O(max(M,n))其中M是最大值,n是测试用例的数量
  • 对于小型测试用例,最好使用内置sorted,即O(nlogn),其中n是样本数

评价

我对随机数组进行了非常简单的测试,显示了与有界数据上大量优化的Timsort相比,(天真实现)countort的执行情况

from timeit import Timer as T
import random

def timsort(x):
    return sorted(x)

def countsort(x):
    m = max(x)
    buckets = [0] * (m+1)
    for a in x: buckets[a] += 1
    return [ b for c in ( [a] * buckets[a] for a in xrange(m+1) ) for b in c ]


for t,n in [ (1000,1000), (1000,10000), (10000,10000), (10000,100000), (100000,100000), (100000,1000000) ]:

    print 't=',t,'n=',n

    X = [ random.randint(0,t) for _ in xrange(n) ]

    t = T( lambda: countsort(X) )
    print 'count',t.timeit(number=1000)

    t = T( lambda: timsort(X) )
    print 'timso',t.timeit(number=1000)

结果:

t= 1000 n= 1000
count 0.759298086166
timso 0.296448945999
t= 1000 n= 10000
count 2.71147489548
timso 3.95411610603
t= 10000 n= 10000
count 7.57060909271
timso 4.03612089157
t= 10000 n= 100000
count 28.043751955
timso 59.6779661179
t= 100000 n= 100000
count 78.1641709805
timso 58.4075620174
t= 100000 n= 1000000
count 286.381267071
timso 1023.59388494

看来,如果n>10t(其中t是最大值)那么countort要快得多。否则,Timsort的更好实现优于复杂性。

答案 1 :(得分:0)

你会在Iejlot的回答中找到我的评论,Timsort打败了我的计数排序,尽管几乎没有。我在这里提交给任何人改进它。

d={}
newlist=[]
for i in original_List:
      try:
            d[i]+=1
      except:
            d[i]=1
for x,y in d.items():
      newlist+=[x for t in range(y)]