假设歌曲i
已播放f
i 次,但Zipf's Law预测它会
已经玩过z
i 次。然后,您将歌曲的质量i
定义为q
i = f
i / z
我
。您的软件应选择值q
i 的最高歌曲。
第一行输入包含两个整数n
和m
(1 <= n < 50 000
,1 <= m <= n
),相册中的歌曲数量以及歌曲的数量选择。然后按n
行。这些行中的i
'包含整数f
i 和字符串s
i ,其中0 <= f
<子> I 子> < 10^12
是收听i
首歌曲的次数,s
i 是该歌曲的名称。
每首歌曲名称最多30个字符,仅包含字符a-z
,0-9
和下划线(_
)。
按质量降序输出质量最高的q
i 的m首歌曲列表。如果两首歌曲具有相同的质量,则优先考虑专辑中出现的第一首歌曲(可能是制作人有理由将该歌曲放在另一首歌曲之前)。
sample input
4 2
30 one
30 two
15 three
25 four
sample output
four
two
我是python的新手,我正在尝试解决这个难题我想我得到了正确的答案,但我必须更快地完成任何建议吗?
from __future__ import division
def main():
import sys
from operator import itemgetter
data = sys.stdin.readlines()
line1 = data[0].split(" ")
numberofselect = line1[1]
qualitydict = {};
songdict = {};
a = 0
for x in range(1, len(data)):
item = data[x].split(" ");
item1 = item[1].split("\n");
f = float(item[0])
z = float(1/x)
qualitydict[item1[0]] = (f/z)
if ((f/z) in songdict.keys()):
songdict[(f/z)].append(item1[0])
else:
songdict[(f/z)] = [item1[0]]
items = songdict.items()
items.sort(key = itemgetter(0), reverse=True)
for key, value in items:
for element in value:
if (a < int(numberofselect)):
print element
a = a + 1
main();
答案 0 :(得分:3)
您可以在可读性和性能方面做很多改进[未经测试]:
from __future__ import division
import sys
from operator import itemgetter
from collections import defaultdict
def main():
line1 = sys.stdin.readline().split(" ")
numberofselect = int(line1[1])
qualitydict = {}
songdict = defaultdict(list)
for x, line in enumerate(sys.stdin, start=1):
tokens = line.split()
val = float(tokens[0]) * x
qualitydict[tokens[1]] = val
songdict[val].append(tokens[1])
items = songdict.items()
items.sort(key=itemgetter(0), reverse=True)
a = 0
for key, value in items:
for element in value:
if a < numberofselect:
print element
a += 1
main()
特别是:
defaultdict
使用songdict
。如果密钥不存在,它将自动创建新的list
值。另外:不要使用key in your_dict.keys()
来查看某个键是否在字典中,因为该检查是O(n)
。使用key in your_dict
时间O(1)
。请注意,使用defaultdict
您根本不需要进行检查,它已经为您完成了。
您将z
定义为1/x
然后执行f/z
,但这与执行f * x
相同,唯一的区别是后者会更精确(x
是一个整数,所以做1/x
会失去一些精确度)。
我想知道是否有必要使用op.itemgetter(0)
对项目进行排序。我的意思是,元素是元组,因此它们将首先按第一个键排序,其次按第二个键排序,结果将是您希望按质量和按字母顺序排序的歌曲(当质量为同一首歌不止一首)。请注意,即使您可能认为使用op.itemgetter(0)
进行排序会更快,但我认为这不一定是正确的,因为您为每个元素添加了一个函数调用,而python必须使用一些空间来保持键值
事实上,如果我们检查时间:
>>> timeit.timeit('L.sort()', 'import random;L = [(random.randint(0, 100), i) for i in range(3000)]', number=10000)
1.3252038955688477
>>> timeit.timeit('L.sort(key=operator.itemgetter(0))', 'import random;import operator;L = [(random.randint(0, 100), i) for i in range(3000)]', number=10000)
2.926893949508667
增加itemgetter
版本的性能会有所改善,但是您必须仔细检查它会变得更好,因为即使使用50000
元素:
>>> timeit.timeit('L.sort()', 'import random;L = [(random.randint(0, 1000), i) for i in range(50000)]', number=1000)
13.771193027496338
>>> timeit.timeit('L.sort(key=operator.itemgetter(0))', 'import random;import operator;L = [(random.randint(0, 1000), i) for i in range(50000)]', number=1000)
21.419496059417725
line.split()
没有参数在任何空格上分开。例如:
>>> 'A string with some space,\ttabs and \n\n newlines'.split()
['A', 'string', 'with', 'some', 'space,', 'tabs', 'and', 'newlines']
与以下内容完全不同:
>>> 'A string with some space,\ttabs and \n\n newlines'.split(' ')
['A', 'string', 'with', '', '', 'some', '', '', '', 'space,\ttabs', 'and', '\n\n', 'newlines']