最近在LeetCode上刷题,碰到一些需要计算元素在列表或者字符串中出现频次的题目,比如:
第217题:给定一个整数数组,判断是否存在重复元素。
第350题:给定两个数组,编写一个函数来计算它们的交集。
第1002题:查找常用字符。
第961题:重复N次的元素。
第1122题:数组的相对排序。
。。。。。。
这是我目前刷到过的题目,相信还有很多没刷到的题目也或多或少需要用到对元素出现频次进行统计,下面我就目前用到的方法做一个小结,仅供参考。
arr.count(item)直接返回item在arr中出现的次数,非常方便,但是效率一般,遇到arr非常大的时候,就非常耗时。拿第217题来举例,题目要求判断一个整数数组是否存在重复元素,利用.count()方法很简单,但是在LeetCode中超时!
''' #5: timeout'''
def containsDuplicate5(nums):
for item in nums:
if nums.count(item) > 1:
return True
return False
还以第217题为例,通过在切片列表中进行轮询的方式,也可以得知该元素是否在列表中重复出现,如果想要精确知道出现次数,只需要加一个变量进行累加统计即可,第217题如下的解法也超时!
''' #4: timeout'''
def containsDuplicate4(nums):
for i in range(len(nums)):
if (nums[i] in nums[i+1:]):
return True
return False
这个方法比较常规,就是先将列表进行排序,这样重复的元素就会排列在一起,然后通过逐个轮询比较,就可以判断是否存在重复元素,如果要统计元素的重复次数,增加一个变量来进行累加即可,第217题如下解法耗时216ms,虽然通过了,但效果不是很理想!
''' #6: 216ms'''
def containsDuplicate6(nums):
if (len(nums) == 1):
return False
else:
nums.sort()
for i in range(len(nums)-1):
if (nums[i] == nums[i+1]):
return True
return False
该方法需要导入collections库,然后利用Counter(item)方法返回一个以元素为key,元素的出现次数为value的字典,直接将元素和其出现的次数对应起来了,非常方便,效率也比较高。Counter实际上是collections模块的一个类,其对象能做+、-、&、|等各种算术和集合操作,具体如下:
>>> c = Counter(a=3, b=1)
>>> d = Counter(a=1, b=2)
>>> c + d # add two counters together: c[x] + d[x]
Counter({'a': 4, 'b': 3})
>>> c - d # subtract (keeping only positive counts)
Counter({'a': 2})
>>> c & d # intersection: min(c[x], d[x])
Counter({'a': 1, 'b': 1})
>>> c | d # union: max(c[x], d[x])
Counter({'a': 3, 'b': 2})
详细的用法可以参考官方文档:https://docs.python.org/2/library/collections.html#collections.Counter.most_common
第217题利用Counter的解法如下:
''' #3: using Counter() method. 140ms'''
from collections import Counter
def containsDuplicate3(nums):
for k, v in Counter(nums).items():
if (v > 1):
return True
return False
Counter的对象也是一个字典,因此我们可以利用字典本身的方法,来实现跟Counter一样的功能,这种方式效率高,且不需要导入collections模块,此方法是肖哥教给我的,在此感谢我的人生导师-肖哥!。
第217题本方法的解法如下:
''' #3+: xk's much better version '''
def containsDuplicate33(nums):
dict_nums = {}
for item in nums: #功能类似Counter,生成一个字典,key是列表元素,value是元素出现的次数
dict_nums[item] = dict_nums.get(item, 0) + 1
for k, v in dict_nums.items():
if (v > 1):
return True
return False
以上为个人的总结和积累,备日后复习之用,也希望能帮到有需要的朋友,更加完整、丰富的LeetCode上第217题的解法见如下Github链接:
https://github.com/Ricky-Hu5918/Python-Lab/blob/master/217_Contains_Duplicate.py
也欢迎志同道合的的朋友们一起来LeetCode刷题!