topk 最小
使用大根堆,即子结点的值总是小于它的父节点。
在末尾添加节点,使用sift_up.
删除原来根节点,添加新根节点用sift_down
class Solution {
public:
aaa
public:
vector<int> topKFrequent(vector<int>& nums, int k) {
vector<int> result;
result.push_back(0);
int cur_num;
for(int i =0;i<nums.size();i++){
cur_num=nums[i];
if(i<k){
result.push_back(cur_num);
sift_up(result,i+1);
}else{
if(cur_num<result[1]){
result[1]=cur_num;
sift_down(result,k);
}
}
}
result.erase(result.begin());
return result;
}
};
剑指 Offer 41. 数据流中的中位数
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。
例如,
[2,3,4] 的中位数是 3
[2,3] 的中位数是 (2 + 3) / 2 = 2.5
设计一个支持以下两种操作的数据结构:
void addNum(int num) - 从数据流中添加一个整数到数据结构中。
double findMedian() - 返回目前所有元素的中位数。
示例 1:
输入:
[“MedianFinder”,“addNum”,“addNum”,“findMedian”,“addNum”,“findMedian”]
[[],[1],[2],[],[3],[]]
输出:[null,null,null,1.50000,null,2.00000]
示例 2:
输入:
[“MedianFinder”,“addNum”,“findMedian”,“addNum”,“findMedian”]
[[],[2],[],[3],[]]
输出:[null,null,2.00000,null,2.50000]
限制:
最多会对 addNum、findMedian 进行 50000 次调用
思路:左边为一个大根堆,右边为一个小根堆
当前为奇数个,如果新添加的大于middle就添加到右边,原来的middle添加到左边,然后令右边的最小值为新的middle。
class MedianFinder {
public:
/** initialize your data structure here. */
vector<int> leftnum;
vector<int> rightnum;
int middle;
int total;
MedianFinder() {
total=0;
}
void addNum(int num) {
if(total==0){
middle=num;
total++;
return;
}
if(total%2==1){
if(num<middle){
leftnum.push_back(num);
big_up(leftnum,leftnum.size());
rightnum.push_back(middle);
small_up(rightnum,rightnum.size());
}else{
leftnum.push_back(middle);
big_up(leftnum,leftnum.size());
rightnum.push_back(num);
small_up(rightnum,rightnum.size());
}
total++;
return;
}else{
int left=leftnum[0];
int right=rightnum[0];
if(num>left && num<right){
middle=num;
total++;
return;
}else if(num<=left){
leftnum.push_back(num);
big_up(leftnum,leftnum.size());
middle=leftnum[0];
leftnum[0]=leftnum[leftnum.size()-1];
leftnum.pop_back();
big_down(leftnum,leftnum.size());
total++;
return;
}else{
rightnum.push_back(num);
small_up(rightnum,rightnum.size());
middle=rightnum[0];
rightnum[0]=rightnum[rightnum.size()-1];
rightnum.pop_back();
small_down(rightnum,rightnum.size());
total++;
return;
}
}
}
double findMedian() {
if(total%2==1){
return middle/1.0;
}else{
return (leftnum[0]+rightnum[0])/2.0;
}
}
void big_up(vector<int>& vec, int size){
int cur=size-1;
int p,tmp;
while(cur>0){
p=(cur-1)>>1;
if(vec[cur]>vec[p]){
tmp=vec[p];
vec[p]=vec[cur];
vec[cur]=tmp;
cur=p;
}else{
break;
}
}
return;
}
void small_up(vector<int>& vec, int size){
int cur=size-1;
int p,tmp;
while(cur>0){
p=(cur-1)>>1;
if(vec[cur]<vec[p]){
tmp=vec[p];
vec[p]=vec[cur];
vec[cur]=tmp;
cur=p;
}else{
break;
}
}
return;
}
void big_down(vector<int>& vec, int size){
int cur=0;
int c,cl,cr,tmp;
while(cur<size){
cl=(cur<<1)+1;
cr=cl+1;
if(cl<size){
if(cr>=size || vec[cl]>vec[cr]){
c=cl;
}else{
c=cr;
}
}else{
break;
}
if(vec[cur]<vec[c]){
tmp=vec[c];
vec[c]=vec[cur];
vec[cur]=tmp;
cur=c;
}else{
break;
}
}
return;
}
void small_down(vector<int>& vec, int size){
int cur=0;
int c,cl,cr,tmp;
while(cur<size){
cl=(cur<<1)+1;
cr=cl+1;
if(cl<size){
if(cr>=size || vec[cl]<vec[cr]){
c=cl;
}else{
c=cr;
}
}else{
break;
}
if(vec[cur]>vec[c]){
tmp=vec[c];
vec[c]=vec[cur];
vec[cur]=tmp;
cur=c;
}else{
break;
}
}
return;
}
};