《LeetCode笔记46》:前 K 个高频元素

题目:

给定一个非空的整数数组,返回其中出现频率前 高的元素。

示例 1:

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

示例 2:

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

说明:

  • 你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
  • 你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/top-k-frequent-elements

方法一:哈希表+堆

1.利用字典(哈希表)存储数组中每个元素出现的频率;

2.用一个大小为k的最小堆存储频率大小为前k个的元素。时间复杂度为O(klogk)。

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        self.key_value = {}
        for i in nums:
            if i in self.key_value:
                self.key_value[i] = self.key_value[i]+1
            else:
                 self.key_value[i] = 1
        self.min_heap = []
        for key in self.key_value:
            if k>0:
                self.min_heap.append(key)
                self.up_shift()
                k -= 1
            else:
                if self.key_value[key]>self.key_value[self.min_heap[0]]:
                    self.min_heap[0] = key
                    self.down_shift()
        return self.min_heap[::-1]

    def up_shift(self):
        child_index = len(self.min_heap)-1
        while(child_index>0):
            parent_index = (child_index-1)//2
            if parent_index>=0 and self.key_value[self.min_heap[parent_index]]>self.key_value[self.min_heap[child_index]]:
                c = self.min_heap[child_index]
                self.min_heap[child_index] = self.min_heap[parent_index]
                self.min_heap[parent_index] = c
                child_index = parent_index
            else:
                break

    def down_shift(self):
        l = len(self.min_heap)
        parent_index = 0
        while(parent_index<l-1):           
            left_child = parent_index*2+1
            right_child = left_child+1
            c = self.key_value[self.min_heap[parent_index]]
            index = 0
            if left_child<l and c>self.key_value[self.min_heap[left_child]]:
                index = left_child
                c = self.key_value[self.min_heap[left_child]]
            if right_child<l and c>self.key_value[self.min_heap[right_child]]:
                index = right_child
                c = self.key_value[self.min_heap[right_child]]
            if index!=0:
                c = self.min_heap[index]
                self.min_heap[index] = self.min_heap[parent_index]
                self.min_heap[parent_index] = c
                parent_index = index
            else:
                break 

方法二:哈希表+二分查找

哈希表统计词频,维护一个大小为k的有序列表来存储当前频率为前k个的元素,元素的替换和查找可以使用二分查找。

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        result = []
        counting = {}
        for i in nums:
            if i in counting.keys():
                counting[i]+=1
            else:
                counting[i]=1
            if i in result:
                result.remove(i)
            if not result:
                result.append(i)
            else:
                if counting[i]>=counting[result[-1]]:
                    result.append(i)
                elif counting[i]<=counting[result[0]]:
                    result.insert(0, i)
                else:
                    start = 0
                    end = len(result)
                    while(1):
                        index = (start+end)//2
                        if counting[result[index]]==counting[i]:
                            break
                        elif counting[result[index]]>counting[i]:
                            if counting[result[index-1]]<=counting[i]:
                                break
                            else:
                                end = index
                        else:
                            if counting[result[index+1]]>=counting[i]:
                                index = index+1
                                break
                            else:
                                start = index
                    result.insert(index, i)
            if len(result)>k:
                result.pop(0)
        return result


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值