11.21学习笔记

一.集合(set):集合天生就有从小到大排序的性质,所以他就是一个小顶堆。如果要做一个大顶堆怎么办?可以先将每个元素都取负数,排完序后再取反。        

int main(){
    typedef pair<int,int>p2;
    set<p2>s;//定义pair的目的是为了能让集合可以插入重复的元素,第一个int代表插入的元素,第二个代表插入的编号。
    int tot=0;
    s.insert(p2(3,tot++));//插入指令
    s.insert(p2(4,tot++));
    s.insert(p2(5,tot++));
    for(auto x:s){//x可以类似为一个指针,遍历s的所有元素。
        cout<<x.first<<"  "<<x.second<<endl;
    }
        s.erase(s.begin());//这等价于小顶堆中的pop操作。
        s.insert(p2(10,tot++));//push操作。
    }

二.题目练习:

1.

2.维护数据流中的中位数(对顶堆):

也就是,我们建立前后两个顶堆。如果是奇数个,我们只需要取大顶堆的堆顶元素。否则,就取两个堆的堆顶元素的均值。 这是维护的过程。

如何插入?判断一下新元素和s1堆顶元素的大小关系:如果我比堆顶s1的堆顶还小,那我就去s1中,如果比最大值大,那就去s2;

class MedianFinder {
public:
  typedef pair<int,int>p2;
    set<p2>s1,s2;
    int tot;
    MedianFinder() {
tot=0;   
    }
    void addNum(int num) {
if(s1.size()==0||num<-s1.begin()->first){ s1.insert(p2(-num,tot++));}
    else s2.insert(p2(num,tot++));
    int n1=(s1.size()+s2.size()+1)/2;
    if(n1==s1.size())return;
    if(n1<s1.size()){
        s2.insert(p2(-s1.begin()->first,tot++));
        s1.erase(s1.begin());
    }
    if(n1>s1.size()){
         s1.insert(p2(-s2.begin()->first,tot++));
        s2.erase(s2.begin());
    }
    return;
}
    
    double findMedian() {
        if((s1.size()+s2.size())%2){
            return -s1.begin()->first;
        }
        else {return(-s1.begin()->first+s2.begin()->first)/2.0;}
    }
};

3.合并K个升序链表:

思路:既然链表都已经是有序的了,我们只需要考虑每个链表的头部,并予以比较。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值