这题可以用三种方法去做
目录
1.暴力
对所有的数据直接读入之后用sort排序输出中位数即可。
这里类型转换用了C++11的static_cast<>
由于是一次快排,所以是时间复杂度是O(nlogn)
代码如下所示:
class Solution {
public:
#define SCD static_cast<double>
vector<int> v;
void Insert(int num) {
v.push_back(num);
}
double GetMedian() {
sort(v.begin(), v.end());
int sz=v.size();
if(sz & 1){//奇数则返回中间那位数
return SCD(v[sz>>1]);
}else{
return SCD(v[sz>>1]+v[(sz>>1)-1])/2;
}
}
};
2.插入排序
这里用到了一个lower_bound接口:
其作用是返回数组中第一个大于或等于被查数的值
求中位数的做法和之前没啥不一样的。
这里的时间复杂度对每一个数都是O(logn)的,总的时间复杂度是O(nlogn)
class Solution {
public:
#define SCD static_cast<double>
vector<int> v;
void Insert(int num) {
if(v.empty()){
v.push_back(num);
}else{
auto it=lower_bound(v.begin(), v.end(), num);
v.insert(it, num);
}
}
double GetMedian() {
int sz=v.size();
if(sz&1){
return SCD(v[sz>>1]);
}else{
return SCD(v[sz>>1]+v[(sz>>1)-1])/2;
}
}
};
3.堆
这里学习一下大小顶堆的直接写法:
小顶堆:
priority(int, vector<int>, less<int>)
大顶堆:
priority(int, vector<int>, greater<int>)
我们的任务是维护两个大小顶堆,可以这么理解,我们只需要用两个数把小的和大的两个部分隔开不就好了么,为什么一定要求两个部分有序呢?基于这种考虑,我们采用堆排序。
注意一些细节,小的那一部分存在大顶堆中,大的那一部分存在小顶堆中。
思路如下:
既然是要求中位数,我们希望两个堆的元素数目尽量接近,分为以下几种情况:
1.大顶堆的元素数目多于小顶堆的元素数目,如果这时候我们要把新的数据放进来,显然我们应该放到小顶堆,但是放的是我们当前新加的元素吗?显然不是,我们这个时候要利用大顶堆,先把当前元素放入大顶堆,然后将新生成的堆顶取出放入小顶堆中。
2.其余情况其实差不多,等于其实是随便放到哪个堆的。
这个时候求中位数就根据两个堆的元素数目进行求取就行了
代码如下所示:
class Solution {
public:
#define SCD static_cast<double>
priority_queue<int> min_q;//小顶堆
priority_queue<int, vector<int>, greater<int>> max_q;//大顶堆
void Insert(int num) {
if(max_q.size()>=min_q.size()){
max_q.push(num);
min_q.push(max_q.top());
max_q.pop();
}else{
min_q.push(num);
max_q.push(min_q.top());
min_q.pop();
}
}
double GetMedian() {
if(max_q.size()==min_q.size()){
return SCD(max_q.top()+min_q.top())/2;
}else if(max_q.size()>min_q.size()){
return SCD(max_q.top());
}else{
return SCD(min_q.top());
}
}
};