2020年9月5日 周六 天气晴 【不悲叹过去,不荒废现在,不惧怕未来】
本文目录
题目简介和解法总览
这道题的解法有很多,详见如下:
其中最重要的就是最后两种解法,这里分别用STL
中的multiset
和priority_queue
来实现。当然,另外几种方法也要了解,如果在面试中被问到至少能将方法说清楚。
1. 数组
用数组有两种做法:
1.1 没有排序的数组
先插入元素,然后在无序数组中获取中位数(可以使用快速选择算法,获取无序数组的中位数,参考 剑指offer 39. 数组中出现次数超过一半的数字)。
1.2 排序数组
插入的同时进行排序,然后通过下标返回中位数。
2. 排序链表
类似于 1.2 排序数组 。
3. 二叉搜索树
这需要我们手动实现二叉搜索树,需要编写的有:节点类TreeNode
,添加元素函数addNum()
和查找第k
小的函数searchKth()
。
searchKth()
实现原理:
对于root,计算它的左子树节点个数leftCount
:
- 如果
leftCount + 1 == k
,说明当前root
就是第k
小的元素; - 如果
leftCount + 1 > k
,说明第i小的元素在root
的左子树,进入左子树继续递归查找; - 如果
leftCount + 1 < k
,说明第i小的元素在root
的右子树,需要进入右子树查找,但在右子树中我们要查找的就不再是第k
小的元素,而是排除了左子树和根节点后,第k-leftCount-1
小的元素。
如何计算一棵树的左右节点个数:
在树节点中增加一个size
成员变量,记录以当前节点为根的树有多少个节点(包括当前节点本身),每个新创建的节点的size=1
,每向BST
添加一个新节点,在寻找合适位置过程中,经过的每一个节点的size
都要+1
。
4. multiset (推荐)
class MedianFinder {
private:
multiset<int> data;
multiset<int>::iterator mid;
public:
/** initialize your data structure here. */
MedianFinder() :mid(data.end()) {
}
void addNum(int num) {
const int len = data.