这个问题询问如何确定列表中的每个元素是否相同。如果要以相对高效的方式确定列表中95%的元素是否相同,应该怎么做?例如:
>>> ninety_five_same([1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1])
True
>>> ninety_five_same([1,1,1,1,1,1,2,1]) # only 80% the same
False
这需要有一定的效率,因为列表可能非常大。
这个问题询问如何确定列表中的每个元素是否相同。如果要以相对高效的方式确定列表中95%的元素是否相同,应该怎么做?例如:
>>> ninety_five_same([1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1])
True
>>> ninety_five_same([1,1,1,1,1,1,2,1]) # only 80% the same
False
这需要有一定的效率,因为列表可能非常大。
>>> from collections import Counter
>>> lst = [1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
>>> _, freq = Counter(lst).most_common(1)[0]
>>> len(lst)*.95 <= freq
True
collections
模块中添加Counter
子类时引入的。 - martineau实际上,对于类似问题有一个简单的线性解决方案,仅使用50%约束而不是95%。 查看这个问题,只需要几行代码。
它也适用于你,只需要在最后检查所选元素是否满足95%的阈值,而不是50%。(尽管,正如Thilo所指出的那样,如果currentCount>= n * 0.95,则这不是必要的。)
我还会发布st0le答案中的Python代码,向所有人展示它有多难。
currentCount = 0
currentValue = lst[0]
for val in lst:
if val == currentValue:
currentCount += 1
else:
currentCount -= 1
if currentCount == 0:
currentValue = val
currentCount = 1
如果你正在寻找解释,我认为Nabb提供了最好的解释。
def ninety_five_same(lst):
freq = collections.defaultdict(int)
for x in lst:
freq[x] += 1
freqsort = sorted(freq.itervalues())
return freqsort[-1] >= .95 * sum(freqsort)
def ninety_five_same(lst):
freq = collections.defaultdict(int)
for x in lst:
freq[x] += 1
freq = freq.values()
return max(freq) >= .95 * sum(freq)
内存使用为O(m)。max
和sum
可以用单个循环替代。
lambda: 0
替换为int
,它保证被初始化为0。 - Björn Pollex (1,2,3,4,5,6,7,8,9,10, ... , 100, 42,42, 42, 42 .... 42)
所以我认为,你需要先建立一个频率表,至少要覆盖前5%的表格。
def ninety_five_same(l):
return max([l.count(i) for i in set(l)])*20 >= 19*len(l)
同时还解决了浮点数除法精度的问题。
lst = [1,1,1,1,1,1,2,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1]
#lst = [1, 2, 1, 4, 1]
#lst = [1, 2, 1, 4]
length = len(lst)
currentValue = lst[0]
lst.pop(0)
currentCount = 1
for val in lst:
if currentCount == 0:
currentValue = val
if val == currentValue:
currentCount += 1
else:
currentCount -= 1
percent = (currentCount * 50.0 / length + 50)
epsilon = 0.1
if (percent - 50 > epsilon):
print "Percent %g%%" % percent
else:
print "No majority"
currentCount >= n*0.95
不起作用,因为currentCount的值取决于元素的顺序,但上述方法确实有效。C:\Temp>a.py
[2, 1, 1, 4, 1]
currentCount = 1
C:\Temp>a.py
[1, 2, 1, 4, 1]
currentCount = 2
将排序作为一般解决方案可能会很耗费时间,但考虑到Python中tim sort的卓越平衡性质,它利用了列表的现有顺序。我建议先对列表进行排序(或使用sorted复制),但这样做会影响性能。从前面和后面扫描找到相同的元素或达到扫描长度 > 5%,否则列表与找到的元素相似度为95%。
随机选取元素作为候选项,并按频率降序计数,直到发现计数 > 95%或总计数超过5%,应该也不错。