求解前K个高频元素
题目描述:
给定一个非空的整数数组,返回其中出现频率前 k 高的元素。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:
输入: nums = [1], k = 1
输出: [1]
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/top-k-frequent-elements
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路
求的是前K高频的元素,那首先要统计每个元素出现的次数,并将元素以及其出现的次数以key和value的形式放入一个字典中。然后再以字典中的value(也就是其对应的key出现在原数组中的次数)为准,取出前K高value对应的key放入结果中返回。
主要的问题:
统计每个元素出现的次数只需采用一个for循环即可,用dic_count存放结果
for i in nums: #遍历数组nums,将所有出现的数字及其出现次数保存与dic_count中
if i not in dic_count:
dic_count.update({i: nums.count(i)})
else:
continue
如何方便地取出字典中value前K高的key值,首先想到的是排序,排序之后按照从头到尾的顺序前K个key就非常方便,但是,字典的排序实现比较困难。这里学习了sorted方法和lambda匿名函数,来实现这一算法。
lt = sorted(dic_count.items(), key=lambda x: x[1], reverse=True)
现在看上去是不是一头雾水,先别急,看了下面对sorted()和lambda的解释你就会豁然开朗。
sorted()方法
sorted() 函数与 reversed() 函数类似,该函数接收一个可迭代对象作为参数,返回一个对元素排序的列表。
在交互式解释器中测试该函数,可以看到如下运行过程:
a = [20, 30, -1.2, 3.5, 90, 3.6]
sorted(a)
[-1.2, 3.5, 3.6, 20, 30, 90]
a
[20, 30, -1.2, 3.5, 90, 3.6]
从上面的运行过程来看,sorted() 函数也不会改变所传入的可迭代对象,该函数只是返回一个新的、排序好的列表。
在使用 sorted() 函数时,还可传入一个 reverse 参数,如果将该参数设置为 True,则表示反向排序。例如如下测试过程:
sorted(a, reverse = True)
[90, 30, 20, 3.6, 3.5, -1.2]
在调用 sorted() 函数时,还可传入一个 key 参数,该参数可指定一个函数来生成排序的关键值。比如希望根据字符串长度排序,则可为 key 参数传入 len 函数。例如如下运行过程:
b = ['fkit', 'crazyit', 'charlie', 'fox', 'Emily']
sorted(b, key = len)
['fox', 'fkit', 'Emily', 'crazyit', 'charlie']
通过 sorted() 函数的帮助,程序可对可迭代对象按照由小到大的顺序进行遍历。
lambda匿名函数
现在再回头看看这一行代码:
lt = sorted(dic_count.items(), key=lambda x: x[1], reverse=True)
解释一下就是将dic_count.items()以lambda x:x[1]为关键值反向排序。
lambda x:x[1]则是用到了匿名函数lambda
ambda函数又称匿名函数,匿名函数就是没有名字的函数,函数没有名字也行?
当然可以啦。有些函数如果只是临时一用,而且它的业务逻辑也很简单时,就没必要非给它取个名字不可。
要理解匿名函数,先来看下面一段代码:
add=lambda x,y:x+y
print(add(1,5))
这里的x,y是a的两个参数,冒号后面则是返回值。
也就相当于:
def add(x,y):
return x+y
add(1,5)
所以如果我们再再回来看那一行代码
lt = sorted(dic_count.items(), key=lambda x: x[1], reverse=True)
其实也就是将dic_count.items()以dic_count.items()[1]为关键值反向排序
这样就获得了以元组为元素的列表,而这个列表是按照元祖索引为1的值(也就是出现次数)从大到小排列的,剩下的就很简单了,只需拿出你需要的K个值就可以了。
求解前K个高频元素的源代码:
def topKFrequent(nums, k):
res = []
count = 0
dic_count = {}
for i in nums: # 遍历数组nums,将所有出现的数字及其出现次数保存与dic_count中
if i not in dic_count:
dic_count.update({i: nums.count(i)})
else:
continue
lt = sorted(dic_count.items(), key=lambda x: x[1], reverse=True)
print(lt)
for i in lt: # 将前k高频元素放入res
if count < k:
res.append(i[0])
count += 1
else:
break
print(res)
感想:sorted和lambda真好真好用呀