如何使用大量密钥快速排序dict()?

时间:2011-03-16 02:45:00

标签: python sorting

TLE总是发生在使用python的SBANK SPOJ中。为了解决这个问题,我必须对dict()进行排序,但dict()有大量KEYS(最大值 - 100000)。在我的代码中使用sorted()函数不起作用。有没有快速解决方案?谢谢你的帮助。

我的代码如下:

for j in range(n): # n is the number of keys
        account = sys.stdin.readline().rstrip()
        dic.setdefault(account, 0)
        dic[account] += 1
sorted(dic) # **this sort take a lot of time**

EDIT1 :根据Justin Peel的提示,我在下面更新了我的代码,但仍然返回TLE。我该怎么办?

import sys
import psyco # import psyco module to speed up
psyco.full()
nCase = int(sys.stdin.readline().split()[0])
for i in range(nCase):
    n = int(sys.stdin.readline().split()[0])
    dic = dict()
    lst = list()
    for j in range(n):
        account = sys.stdin.readline().rstrip()
        dic.setdefault(account, 0)
        dic[account] += 1
    sys.stdin.readline()
    lst = dic.keys() # store keys in list
    lst.sort()
    for account in lst:
        sys.stdout.write('%s %s\n' % (account, dic[account]))

3 个答案:

答案 0 :(得分:2)

dict未排序,这是他们能够提供O(1)插入和获取访问权限的方式。 (在内部,它们被实现为哈希表,我相信,虽然我不确定这是Python规范要求的。)

如果要按排序顺序迭代dict的键,可以使用:

for key in sorted(the_dict.iterkeys()):
    value = the_dict[key]
    # do something

但是,正如您所注意的,排序100,000个元素可能需要一些时间。

作为替代方案,您可以编写(或在互联网上查找)已排序的dict实现,这些实现保留按键的有序列表以及字典,并支持按键快速查找,并按顺序迭代而不必一次排序。当然,为了支持排序顺序,密钥需要在插入时进行排序,因此插入不会是O(1)。

编辑:根据dsolimano的评论,如果您使用的是Python 2.7或Python 3.x,则会有一个内置的OrderedDict类来命令迭代插入顺序。这样可以保持快速插入,但可能无法满足您的需求(取决于您想要的项目顺序)。

答案 1 :(得分:1)

我能够解决这个问题。以下是一些提示:

  1. 使用Python 2.5。它比Python 3.2快得多,后者是SPOJ上使用Python的另一个选项。只有一个人能够使用Python 3.2获得足够快的解决方案
  2. 只需使用基本字典进行计数。您也可以使用collections模块中的defaultdict,但基本的dict对我来说更快。
  3. 仅对dict的键进行排序,而不是键 - 项对。形成关键项对需要太长时间。另外,使用keys = mydict.keys(); keys.sort()因为这是最快的方法。
  4. 使用psyco(几乎总是使用Python中的SPOJ问题)
  5. 了解在Python中进行输入和输出的最快方法。提示:例如,它不会迭代每一行输入。
  6. 尝试在添加完每个部分(获取输入,计数,输出)后提交,以便随时查看您的位置。这对SPOJ来说是非常有价值的。运行代码的SPOJ计算机很可能比您当前的计算机慢很多,如果它对SPOJ足够快,很难根据您自己计算机的代码运行时间来确定。

答案 2 :(得分:0)

由于Python 3.1可用,collections.Counter适用于此目的:

collections.Counter(map(str.rstrip, sys.stdin)).most_common()