剑指offer 63、64:数据流中的中位数 、滑动窗口的最大值

63.题目描述
如何得到一个数据流中的中位数?如果从数据流中读出奇数个数值,那么中位数就是所有数值排序之后位于中间的数值。如果从数据流中读出偶数个数值,那么中位数就是所有数值排序之后中间两个数的平均值。我们使用Insert()方法读取数据流,使用GetMedian()方法获取当前读取数据的中位数。
思路:堆插入时间复杂度O(log n)
设置最大堆 最小堆。其中最大堆的最大值<=最小堆的最小值
最大堆p–top—–top—最小堆q
插入:当p为空或者num

class Solution {
    priority_queue<int,vector<int>,less<int> >p;//less最大堆
    priority_queue<int,vector<int>,greater<int> >q;//最小堆
public:
    bool err_flag=false;//非法操作
    void Insert(int num)
    {
        if(p.empty()||num<p.top())//先放在最大堆中
            p.push(num);
        else
            q.push(num);
        if(p.size()>q.size()+1)//p与q的差值不能大于1
        {
            q.push(p.top());
            p.pop();
        }
        if(p.size()<q.size())//p与q的差值不能小于0
        {
            p.push(q.top());
            q.pop();
        }
    }

    double GetMedian()
    { 
        if(p.empty())
        {
            err_flag=true;
            return -1;
        }
        return p.size()==q.size()?(p.top()+q.top())/2.0 : p.top();
    }

};

class Solution {
    vector<int>max;
    vector<int>min;
public:
    bool err_flag=false;
    //奇数放在最小堆,偶数放在最大堆
    void Insert(int num)
    {
        if((max.size()+min.size())%2==0)//odd
        {
            if(min.size()>0 && min[0]<num)
            {
                min.push_back(num);
                push_heap(min.begin(),min.end(),greater<int>());
                num=min[0];
                pop_heap(min.begin(),min.end(),greater<int>());
                min.pop_back();
            }
            max.push_back(num);
            push_heap(max.begin(),max.end(),less<int>());
        }
        else
        {
            if(max.size()>0 && max[0]>num)
            {
                max.push_back(num);
                push_heap(max.begin(),max.end(),less<int>());
                num=max[0];
                pop_heap(max.begin(),max.end(),less<int>());
                max.pop_back();
            }
            min.push_back(num);
            push_heap(min.begin(),min.end(),greater<int>());
        }
    }

    double GetMedian()
    { 
        if(min.size()+max.size()==0)
        {
            err_flag=true;
            return 0;
        }
        return (max.size()+min.size())%2==1 ? max[0]:(max[0]+min[0])/2.0;
    }

};

64.题目描述
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。

class Solution {
public:
    vector<int> maxInWindows(const vector<int>& num, unsigned int size)
    {
        vector<int>data;
        if(num.size()<size || size==0)
            return data;
        deque<int>index;
        for(int i=0;i<num.size();++i)
        {
            while(index.size() && num[index.back()]<num[i])//删除比当前值小的坐标
                index.pop_back();
            while(index.size() && i-index.front()+1>size)//删除失效坐标
                index.pop_front();
            index.push_back(i);
            if(i+1>=size)
                data.push_back(num[index.front()]);
        }
        return data;
    }
};

猜你喜欢

转载自blog.csdn.net/zd_nupt/article/details/81704319