我正在使用Hackerrank进行Python 3学习。
在任务Most Common中,您将获得一个仅包含小写英文字符的字符串,您需要找到该字符串中最常见的三个字符。
我遇到了一些问题。
我对此问题的解决方案如下:
#!/bin/python3
import sys
if __name__ == "__main__":
s = input().strip()
ch_dict = {}
for ch in s:
if ch in ch_dict : ch_dict[ch] +=1
else: ch_dict[ch] = 1
result = sorted(ch_dict.items(),key=lambda d:d[1],reverse=True)
for i in result:
if i[1] != 1:
print(" ".join(map(str,i)))
当我在本地环境中测试此代码时,它可以工作!
但在线测试中,可能失败!
对于此输入:
aabbbccde
我提交了很多次,有时会得到这样的正确答案:
b 3
a 2
c 2
也可以得到这个:
b 3
c 2
a 2
似乎排序可能不稳定?或者我的代码有什么关系?或者在Hackerrank环境中出了什么问题?
我如何保证输出?
答案 0 :(得分:5)
Python词典无序。当您迭代其内容时,顺序取决于实现,请参阅Why is the order in dictionaries and sets arbitrary?
您只按值对商品进行排序,因此,如果您按任意顺序列出商品,有时('a', 2)
对将首先出现,有时为('c', 2)
对是。
如果您想要稳定订单,也可以通过对键进行排序来打破值之间的联系。
您的挑战声明:
按出现次数的降序对输出进行排序 如果出现次数相同,则按升序对字符进行排序。
因此您需要先按值排序,然后按键,这两个之间的方向不同。
您可以通过两次排序或对逆分数进行排序来实现此目的:
# Sort forward by key, to produce a stable order between keys
by_key = sorted(ch_dict.items(), key=lambda d: d[0])
# Sort backward by value, ties are left in the original order, so by key
result = sorted(by_key, key=lambda d: d[1], reverse=True)
或一步到位:
sorted(ch_dict.items(), key=lambda d: (-d[1], d[0]))
按否定计数排序,然后按键排序,不要反转。
请注意,挑战实际上只询问前三个字符。挑战不使用大量输入,但如果有,那么使用排序实际上是低效的。您不需要排序所有键值对,只需排在前3位。您如何才能获得前3名?您可以使用heap queue,它可以有效地为您提供任何序列的前N个:
import heapq
result = heapq.nsmallest(3, ch_dict.items(), key=lambda d: (-d[1], d[0]))
如果排序需要O(NlogN)时间(N是字典的大小),则heapq需要O(NlogK)时间,N是相同的值,但K是最高项的计数;这里是3.对于包含10,000个项目的字典,排序需要大约133k步才能完成,但堆队列只需要16k步。这几乎要快10倍!
答案 1 :(得分:3)
问题在于:
key=lambda d:d[1]
键仅考虑第二个值,而是使用两个值。
答案 2 :(得分:2)
字典无序。您只按值对输出进行排序,但由于原始字典中的键顺序无法保证,因此输出中每个值的排序可能会有所不同。
您可以通过以下两种方式进行排序来解决此问题:
sorted(ch_dict.items(), key=lambda d: (d[1], d[0]), reverse=True)
答案 3 :(得分:0)
dict.items
可以按任何顺序返回(键,值)对,取决于实现或键插入顺序等细节。 sorted
然后以dict.items
返回的顺序迭代这些对。
如果您需要确定性输出,请使用key=lambda d: (d[1], d[0])
,以便按字典顺序对键(键,值)对进行排序(如果值恰好相同)。
(如果您使用的是Python 2,key=lambda key, value: (value, key)
看起来更好。)
答案 4 :(得分:0)
sorted()
is actually stable因为它保留了与您提供的关键功能提取的密钥相同的项目顺序 - 在这种情况下,密钥是值。但由于dict
s是无序的,因此对于具有相同值的项目,保留的顺序是未定义的。
解决方案是按(value, key)
元组排序:
result = sorted(ch_dict.items(), key=lambda d: (-d[1], d[0]))
注意删除的反转参数,替换为否定值,因为您似乎希望按升序对键进行排序,并按降序对值进行排序。
答案 5 :(得分:0)
在Hackerrank层次结构中,您位于Collections部分。所以解决方案可能是:
#!/bin/python3
import sys,collections
if __name__ == "__main__":
s = 'abcdebbca' # input().strip()
res=collections.Counter(s).items(s)
sortres= sorted ( res, key=(lambda x : (-x[1],x[0])))
for k,v in sortres[:3] : print k,v
行sortres= sorted ( res, key=(lambda x : (-x[1],x[0])))
是必要的,如@Martijn Pieters所解释的那样。
修改强>
由于问题来自dict
,另一个仅使用lists
,sets
和sorted
稳定性的答案:
import sys
if __name__ == "__main__":
s = raw_input().strip()
set_k, list_kv = set() , list()
for x in sorted(s):
if x not in set_k:
if set_k : list_kv.append((-count,val))
set_k.add(x)
count , val = 0 , x
count+=1
for k,v in sorted(list_kv)[:3] : print v,-k