c++ 堆排序

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;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值