所以,这是我在作业中给出的一个问题:
写一个函数,多数(a),返回一个至少出现len(a)// 2 + 1次的值。如果a中不存在这样的元素,则此函数返回None。
任务中的想法是尽可能以最快的方式提出。
我的想法是保留一个包含每个元素计数的字典,然后循环遍历字典以查看是否有任何元素具有len(a)// 2 +1的计数。
但这似乎不太好用。有人可以给我一个更好的解决方案并向我解释一下吗?出于某种原因,这让我疯狂。
这是我结构糟糕的代码:
numTimes = dict()
target = (len(a)//2)+1
for i in range(0, len(a)):
numTimes[str(a[i])] += 1
for k, v in numTimes.iteritems():
if v==str(target):
return v
return None
顺便说一句,让我疯狂的是,当我尝试添加一个新词典元素时出现了一个关键错误,尽管这与这个问题无关。
答案 0 :(得分:1)
我会使用Counter from collections库。它是dict的子类。
from collections import Counter
def majority(iterable):
c = Counter(iterable)
value, count = c.most_common(1)[0]
target = (len(iterable)//2) + 1
if (count >= target):
return value
else:
return None
答案 1 :(得分:0)
首先,考虑len(list)//2+1
意味着有问题的元素需要成为列表的大部分。只能有一个值或没有值满足此值。
您使用字典的感觉是正确的。您可以将每个元素的值映射到每个元素的计数。如果任何元素的计数大于你的答案len(list)//2+1
。
这是计算列表中元素的最简单方法(至少不使用库):
def majority(li):
''' test list li if any single element occurs in li more than len(li)//2+1 times '''
count=dict()
tgt=len(li)//2+1
# count each element in li:
for key in li:
if key in count:
count[key]+=1
else:
count[key]=1
print count
for k, v in count.items():
if v>=tgt:
return k
return None
注意两件事。由于您最终会将li
的每个值设置为0,因此您可以将该部分简化为使用fromkeys()方法并使用set来一次性设置它们:
count={}.fromkeys(set(li),0)
您还可以查看在添加元素时是否获得了多数:
def majority2(li):
''' test list li if any single element occurs in li more than len(li)//2+1 times '''
count={}.fromkeys(set(li),0)
tgt=len(li)//2+1
# count each element in li:
for key in li:
count[key]+=1
if count[key]>=tgt:
return key
return None
测试:
>>> a=['1']*10+['2']*11
>>> majority(a)
{'1': 10, '2': 11}
'2'
>>> majority2(a)
'2'
>>> a=['1']*10+['2']*10
>>> majority2(a)
None
答案 2 :(得分:0)
我发现最有效的方法是:
numTimes = dict()
target = (len(a)//2)+1
for ele in a:
if ele not in numTimes:
numTimes[ele] = 1
else:
numTimes[ele] +=1
if numTimes[ele] == target:
return ele
当我们添加时,我们可以检查次数是否等于我们的目标中点。