一、问题重述
问题描述
给你一个整数数组 nums 和一个整数 k,请你用一个字符串返回其中出现频率前 k 高的元素。请按升序排列。
你所设计算法的时间复杂度必须优于 O(n log n),其中 n 是数组大小。
输入
- nums: 一个正整数数组
- k: 一个整数
返回
返回一个包含 k 个元素的字符串,数字元素之间用逗号分隔。数字元素按升序排列,表示出现频率最高的 k 个元素。
参数限制
- 1 <= nums[i] <= 10^4
- 1 <= nums.length <= 10^5
- k 的取值范围是 [1, 数组中不相同的元素的个数]
- 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的
测试样例
样例1:
输入:
nums = [1, 1, 1, 2, 2, 3], k = 2
输出:"1,2"
解释:元素 1 出现了 3 次,元素 2 出现了 2 次,元素 3 出现了 1 次。因此前两个高频元素是 1 和 2。
样例2:
输入:
nums = [1], k = 1
输出:"1"
样例3:
输入:
nums = [4, 4, 4, 2, 2, 2, 3, 3, 1], k = 2
输出:"2,4"
二、解题思路
- 统计频率:首先,我们需要统计数组中每个元素的出现频率。可以使用
collections.Counter来快速实现这一点。 - 按频率排序:接下来,我们需要根据频率对元素进行排序。由于题目要求时间复杂度优于
O(n log n),我们可以使用堆(heap)来实现这一步。 - 选择前 k 个元素:从堆中取出前
k个频率最高的元素。 - 按升序排列:最后,将这些元素按升序排列,并转换为字符串格式。
三、参考代码讲解
from collections import Counter
import heapq
def solution(nums, k):
# 统计每个元素的频率
frequency = Counter(nums)
# 使用堆来获取前 k 个高频元素
# 这里我们使用最小堆,因为我们只需要前 k 个元素
heap = []
for num, freq in frequency.items():
# 将频率和元素的负值(因为我们需要最大堆)放入堆中
heapq.heappush(heap, (freq, -num))
# 如果堆的大小超过 k,弹出最小的元素
if len(heap) > k:
heapq.heappop(heap)
# 从堆中取出前 k 个元素,并按升序排列
result = []
while heap:
freq, num = heapq.heappop(heap)
result.append(-num)
# 将结果转换为字符串格式
return ','.join(map(str, sorted(result)))
if __name__ == "__main__":
# You can add more test cases here
print(solution([1,1,1,2,2,3], 2) == "1,2")
print(solution([1], 1) == "1")
关键步骤解释
- 统计频率:使用
Counter来统计每个元素的出现频率。 - 使用堆:我们使用最小堆来维护前
k个高频元素。每次插入元素时,如果堆的大小超过k,则弹出最小的元素。 - 取出结果:从堆中取出前
k个元素,并按升序排列。 - 转换为字符串:将结果转换为字符串格式,元素之间用逗号分隔。
四、AI刷题心得
通过近一个月的刷题,感觉豆包Mars Code进步很大,从最开始需要prompt多次才能找出正确答案,到现在对的一次prompt就可以出来正确解答,确实很不可思议。豆包每次给的解题思路也很准确,但是我认为不应太过于依赖AI,要先自己多思考,建立好自己刷题的思维,真是到实在解决不了的问题再问它。