堆
1 什么是堆?
堆是一种有自己规则的树,分为最大堆和最小堆。堆从上往下数值增加或者减小,分别对应最小堆和最大堆。
最大堆:
最小堆:
堆不仅仅可以是二叉树,还可以是多叉树。但它得是完全(complete)树(除了倒数第一层外,其余层需要完全填充)。不同类型的树,堆的搜索、插入、删除有很大的不同。
下面以最大堆(完全二叉树)为例来看堆的操作。
2 堆的搜索
从堆头开始,依次往下比较。
放一个简单的最大堆在这,并在最大堆中搜索2
:
这种情况属于最差的情况,需要搜索整颗树。所以最差时间复杂度是O(n)
。
如果在最大堆中搜索8
,那么直接在堆头就可以返回结果:没有。因为堆头为最大值,而8
大于堆头。这种情况属于最好的情况,时间复杂度为O(1)
。
如果在最大堆中搜索6
,情况如下: 搜索一半左右的节点后发现它大于某个节点的值,那么便不用往下再去搜索了,因为当前节点的值大于其孩子节点的值。这种情况属于平均情况,时间大约是O(n/2)
,也就是O(n)
。
3 python实现堆
3.1 利用heapq模块
实际上,虽然python中没有独立的堆模块,但是拥有包含堆操作函数的模块:heapq,其中堆相关的函数为:
函数 | 解释 |
---|---|
heappush(heap, x) |
将x压入堆中 |
heappop(heap) |
弹出堆顶元素 |
heapify(heap) |
让列表heap具备堆特征 |
heapreplace(heap, x) |
弹出堆顶元素,并将x压入堆中 |
注意:heapq模块默认的堆是最小堆。如果需要最大堆,使用一个转换的trick就好。
- 最小堆示例:
1 | from heapq import * |
- 最大堆示例:
1 | from heapq import * |
3.2 自己实现堆结构
因为python提供的list实际上是一个线性表(Array),但因为
4 LeetCode编程题
4.1 数据流中的中位数(295)
题目链接:https://leetcode-cn.com/problems/find-median-from-data-stream/
- 题目内容
中位数是有序列表中间的数。如果列表长度是偶数,中位数则是中间两个数的平均值。
例如,
[2,3,4]的中位数是 3
[2,3] 的中位数是 (2 + 3) / 2 = 2.5
设计一个支持以下两种操作的数据结构:
- void addNum(int num) - 从数据流中添加一个整数到数据结构中。
- double findMedian() - 返回目前所有元素的中位数。
示例: 1
2
3
4
5addNum(1)
addNum(2)
findMedian() -> 1.5
addNum(3)
findMedian() -> 2
如果数据流中所有整数都在 0 到 100 范围内,你将如何优化你的算法? 如果数据流中 99% 的整数都在 0 到 100 范围内,你将如何优化你的算法?
- python解法
本题参考题解:推荐一个很好的思路
1 | # |