[leetcode]347. 前 K 个高频元素(堆)

1.题目

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

示例 1:

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

输入: nums = [1], k = 1
输出: [1]
2.代码

使用堆处理问题(堆排序):

****************************
堆即用数组表示的树状结构
****************************

1.使用库函数:

class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
        count_dic = collections.Counter(nums)
        items = list(count_dic.items())
        max_heap = []
        for i in items:
            heapq.heappush(max_heap,(-i[1],i[0]))
        res = []
        while k >0:
            res.append(heapq.heappop(max_heap)[1]) 
            k-=1
        return res

2.使用小跟堆求topk大问题:

'''
维护一个长度为k 的堆。
topk小:构建一个 k 个数的大根堆,当读取的数小于根节点时,替换根节点,向下调整。
topk大:构建一个 k 个数的小跟堆,当读取的数大于根节点时,替换根节点,向下调整。
以 topk 大为例: 小跟堆 ==> 越往上越小,若小于跟则小于整个堆,对大小为k ⇒ 有k个比它大的数就不是k大。
'''
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
    	# 向下调整
        def adjustDown(A,k,lens):
        	# A[0]用于暂存A[K],真正的heap是A[1:]
            A[0] = A[k]
            i = 2*k
            while i<lens:
                if i+1<lens and A[i][1]>A[i+1][1]:
                    i +=1
                if A[0][1] <= A[i][1]: break
                else:
                    A[k] = A[i]
                    k = i
                i *=2
            A[k] = A[0]        
        # 建堆    
        def buildMinHeap(A,lens):
            i = lens//2
            while i>0:
                adjustDown(A,i,lens) 
                i -=1
		# 交换函数
        def swap(t1,t2):
            return t2,t

        count_dic = collections.Counter(nums)
        items = list(count_dic.items())
        # A[0]用来暂存A[K]的,真正的heap是A[1:],所以heap长度+1
        heap = [(0,0)]       
        # 建大小为k+1的堆
        for i in range(k):
            heap.append(items[i])
        buildMinHeap(heap,k+1)
        # 若大于跟则替换向下调整
        for i in range(k,len(items)):
            if items[i][1]>heap[1][1]:
                heap[1] = items[i]
                adjustDown(heap,1,k+1)
        # 舍A[0]
        return [t[0] for t in heap[1:]]

3.使用大跟堆求topk大问题:

'''
即堆排序
'''
class Solution:
    def topKFrequent(self, nums: List[int], k: int) -> List[int]:
    	# 向下调整
        def adjustDown(A,k,lens):
        	# A[0]用于暂存A[K],真正的heap是A[1:]
            A[0] = A[k]
            i = 2*k
            while i<lens:
                if i+1<lens and A[i][1]<A[i+1][1]:
                    i +=1
                if A[0][1] >= A[i][1]: break
                else:
                    A[k] = A[i]
                    k = i
                i *=2
            A[k] = A[0]                    
		# 建堆
        def buildMaxHeap(A,lens):
            i = lens//2
            while i>0:
                adjustDown(A,i,lens) 
                i -=1
		# 交换
        def swap(t1,t2):
            return t2,t1
		# 堆排序,将前k大加入res
		# 将最后一位与A[1]交换,并从A[1]开始向下调整
        def heapSort(A,lens,res,k):
            i = lens-1
            while i>=1 and k>0:
                # print(A)
                res.append(A[1][0])
                A[i],A[1] = swap(A[i],A[1])              
                adjustDown(A,1,i)
                i -=1
                k -=1

        count_dic = collections.Counter(nums)
        items = list(count_dic.items())
        # A[0]用来暂存A[K]的,真正的heap是A[1:],所以heap长度+1
        heap = [(0,0)]
        # 建立大小为len(items)+1 的堆
        lens = len(items)
        for i in range(lens):
            heap.append(items[i])
        buildMinHeap(heap,lens+1)
        res = []
        heapSort(heap,lens+1,res,k)     
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值