347. 前 K 个高频元素

  1. 前 K 个高频元素

原始题目链接:https://leetcode-cn.com/problems/top-k-frequent-elements/

给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。

示例 1:

输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:

输入: nums = [1], k = 1
输出: [1]

解题思路:

统计数组的数字个数,存到字典中,字典按照value排序,然后取出前k个即可。

代码实现:

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        dic = {}
        res = []

        for item in nums:
            if item in dic:
                dic[item] += 1
            else:
                dic[item] = 1
        # ans是列表,列表中的元素是元组(key, value)
        ans = sorted(dic.items(), key=lambda x : x[1], reverse=True)
        count = 0
        for i in ans:
            if count >= k:
                break
            res.append(i[0])
            count += 1

        return res

解法2:

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        count = collections.Counter(nums)
        count_list_value = list(count.values())
        count_dict = dict(count.items())
        self.topk_split(count_list_value, len(count_list_value) - k, 0, len(count_list_value) - 1)
        res = count_list_value[len(count_list_value)-k:]
        ans = []
        for i in res:
            for k, v in count_dict.items():
                if v == i:
                    ans.append(k)
                    count_dict.pop(k)
                    break
        return ans

    
    def partition(self, nums, left, right):
        # 初始化一个待比较的基准数据,一般选择待排序数组的第一个数据
        pivot = nums[left]
        # 设置两个指针i, j分别指向待排序数组的开头和结尾
        i, j = left, right

        # 开始遍历待排序数组,结束的循环条件是开头指针超出结尾指针
        while i < j:
            # 从待排序数据的结尾开始查找比较元素的大小,直到找到一个元素比pivot小
            while i < j and nums[j] >= pivot:
                j -= 1
            # 退出上层的while循环表示,找到了一个元素nums[j]比pivot小
            # 让nums[j]放在第i个位置上
            nums[i] = nums[j]
            # 由于刚才的数据交换,指针现在位于第i个位置,
            # 所以从待排序数据的第i个位置开始查找比较元素的大小,直到找到一个元素比pivot大
            while i < j and nums[i] <= pivot:
                i += 1
            # 找到了一个元素nums[i]大于pivot
            # 将这个nums[i]赋值给pivot右边的第j个元素
            nums[j] = nums[i]

        # 一趟快速排序结束之后,pivot的左边都是比它小的元素,右边都是比它大的元素
        # pivot放在中间的位置,最外层while循环结束,此时i和j相等,所以i和j的索引都可以
        # 用来赋值pivot
        nums[i] = pivot

        # 可以返回此时的pivot在数组中的索引
        return i


    def topk_split(self, nums, k, left, right):
        #寻找到第k个数停止递归,使得nums数组中index左边是前k个小的数,index右边是后面n-k个大的数
        if (left < right):
            index = self.partition(nums, left, right)
            if index == k:
                return 
            elif index < k:
                self.topk_split(nums, k, index+1, right)
            else:
                self.topk_split(nums, k, left, index-1)

解法3:

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        freq_dic = {}
        heap = []
        ans = []
        # 统计频数
        for num in nums:
            freq_dic[num] = freq_dic.setdefault(num, 0) + 1
        
        for key, value in freq_dic.items():
            heapq.heappush(heap, (-value, key))

        for _ in range(k):
            ans.append(heapq.heappop(heap)[1])

        return ans
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值