堆的定义 堆(Heap)是一种特殊的树形数据结构,通常是一个完全二叉树。在堆中,每个节点都满足堆的性质:
最大堆:父节点的值大于或等于其所有子节点的值。例如,在最大堆中,根节点是整个堆中的最大值。
最小堆:父节点的值小于或等于其所有子节点的值。在最小堆中,根节点是整个堆中的最小值。
堆的存储 堆通常使用数组来实现存储。对于完全二叉树,假设根节点存储在数组索引为 0 的位置,对于任意节点存储在数组索引为 i 的位置:
它的左子节点存储在数组索引为 2 * i + 1
的位置。
它的右子节点存储在数组索引为 2 * i + 2
的位置。
它的父节点存储在数组索引为 (i - 1) // 2
的位置(向下取整)。
堆的基本操作
插入元素:
先将新元素添加到堆的末尾(数组的最后一个位置)。
然后将新元素与其父节点进行比较,如果不满足堆的性质,则与父节点交换位置。
重复这个过程,直到新元素满足堆的性质或者到达根节点。
删除元素:
在最大堆中,删除操作通常是删除根节点(最大值)。将根节点与堆的最后一个元素交换位置,然后删除最后一个元素。
新的根节点可能不满足堆的性质,需要将其与子节点进行比较并交换,直到满足堆的性质。这个过程称为堆化(Heapify)。
构建堆:
可以从一个无序的数组构建堆。从最后一个非叶子节点开始,对每个非叶子节点执行堆化操作,直到整个数组满足堆的性质。
堆的应用场景
堆排序:利用堆的性质进行排序。可以在O(nlogn)
时间复杂度内对数组进行排序。
优先队列:堆可以高效地实现优先队列。优先队列是一种数据结构,其中每个元素都有一个优先级,元素按照优先级出队。例如,在操作系统中,任务调度可以使用优先队列,高优先级的任务先执行。
Dijkstra 算法:用于在图中求单源最短路径,算法中使用最小堆来存储未确定最短路径的节点,每次从堆中取出距离源点最短距离的节点进行松弛操作。
前K个高频元素
Link: https://leetcode.cn/problems/g5c51o/description/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 def heapAppend (heap, nMap, num ): heap.append(num) cur = len (heap) - 1 parent = (cur - 1 ) // 2 while parent >= 0 : if nMap[heap[cur]] < nMap[heap[parent]]: heap[cur], heap[parent] = heap[parent], heap[cur] cur = parent parent = (cur - 1 ) // 2 def heapify (heap, nMap, i ): if i >= len (heap): return leftChild = 2 * i + 1 rightChild = 2 * i + 2 minEle = i if leftChild < len (heap) and nMap[heap[leftChild]] < nMap[heap[minEle]]: minEle = leftChild if rightChild < len (heap) and nMap[heap[rightChild]] < nMap[heap[minEle]]: minEle = rightChild if minEle != i: heap[minEle], heap[i] = heap[i], heap[minEle] heapify(heap, nMap, minEle) def stack (heap, nMap, k ): for num in nMap.keys(): if len (heap) < k: heapAppend(heap, nMap, num) else : if nMap[num] < nMap[heap[0 ]]: continue else : heap[0 ] = num heapify(heap, nMap, 0 ) class Solution : def topKFrequent (self, nums: List [int ], k: int ) -> List [int ]: nMap = {} heap = [] for num in nums: if num not in nMap: nMap[num] = 1 else : nMap[num] += 1 stack(heap, nMap, k) return heap
用Python的heapq实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 import heapqdef stack (heap, nMap, k ): for num in nMap.keys(): if len (heap) < k: heapq.heappush(heap, (nMap[num], num)) else : if nMap[num] < heap[0 ][0 ]: continue else : heapq.heapreplace(heap, (nMap[num], num)) class Solution : def topKFrequent (self, nums: List [int ], k: int ) -> List [int ]: nMap = {} heap = [] for num in nums: if num not in nMap: nMap[num] = 1 else : nMap[num] += 1 stack(heap, nMap, k) return [x[1 ] for x in heap]