问题描述
中位数是有序整数列表中的中间值。如果列表的大小是偶数,则没有中间值,中位数是两个中间值的平均值。
- 例如
arr = [2,3,4]
的中位数是3
。- 例如
arr = [2,3]
的中位数是(2 + 3) / 2 = 2.5
。实现 MedianFinder 类:
MedianFinder()
初始化MedianFinder
对象。
void addNum(int num)
将数据流中的整数num
添加到数据结构中。
double findMedian()
返回到目前为止所有元素的中位数。与实际答案相差10-5
以内的答案将被接受。
示例
示例 1:
输入 ["MedianFinder", "addNum", "addNum", "findMedian", "addNum", "findMedian"] [[], [1], [2], [], [3], []] 输出 [null, null, null, 1.5, null, 2.0] 解释 MedianFinder medianFinder = new MedianFinder(); medianFinder.addNum(1); // arr = [1] medianFinder.addNum(2); // arr = [1, 2] medianFinder.findMedian(); // 返回 1.5 ((1 + 2) / 2) medianFinder.addNum(3); // arr[1, 2, 3] medianFinder.findMedian(); // return 2.0提示:
-10^5 <= num <= 10^5
- 在调用
findMedian
之前,数据结构中至少有一个元素- 最多
5 * 104
次调用addNum
和findMedian
问题分析:
首先,中位数的概念我们要知道,先把一个数组排序,然后如果数组个数是偶数,去找中间俩数求平均,奇数的话就是只要中间那个数。那么怎么对数组排序事实上是重中之重,因为一旦有序,只要一个for循环中位数就能出来。官解使用的是两个优先队列,但是我作为一个算法小白,在这里分享一下我的辣鸡做法,用multiset来做。
代码如下:
class MedianFinder {
public:
// set本身有序,multiset来确保可以存储重复元素
multiset<int> st;
MedianFinder() {
}
// 无脑大胆插,底层帮你实现
void addNum(int num) {
st.insert(num);
}
double findMedian() {
// 数组的中间节点下标
int n = st.size() / 2;
double res;
if(st.size() % 2 == 0){
// 偶数个元素
int k = 0;
for(auto it = st.begin(); k != n; ++it, ++k){
if(k == n - 1){
int num1 = *it;
++it;
int num2 = *it;
res = (num1 + num2) / 2.0;
}
}
}else{
// 奇数个元素
int k = 0;
// 如果只有一个元素,返回它
if(st.size() == 1) return *st.begin();
for(auto it = st.begin(); k != n; ++it, ++k){
if(k == n - 1){
++it;
int num1 = *it;
res = num1;
}
}
}
// 否则就是遍历,偶数求平均,奇数找中间的,最后返回结果
return res;
}
};
/**
* Your MedianFinder object will be instantiated and called as such:
* MedianFinder* obj = new MedianFinder();
* obj->addNum(num);
* double param_2 = obj->findMedian();
*/