滑动窗口相关问题-算法题

滑动窗口平均值

queue<int> q;
int sum, siz;
MovingAverage(int size) {
    sum = 0;
    siz = size;
}
double next(int val) {
    q.push(val);
    sum += val;
    if (q.size() > siz) {
        sum -= q.front();
        q.pop();
    }
    return 1.0*sum/q.size();
}

滑动窗口最大值

// 优先队列 O(nlogn)
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
    vector<int> ret;
    if (nums.empty() || !k) return ret;
    priority_queue<pair<int,int>> Q;
    for (int i = 0; i < k; ++i)
        Q.push({nums[i], i});
    ret.push_back(Q.top().first);
    for (int i = k; i < nums.size(); ++i) {
        Q.push({nums[i], i});
        while (Q.top().second <= i-k)
            Q.pop();
        ret.push_back(Q.top().first);
    }
    return ret;
}

// 单调队列 O(n)
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
    vector<int> ret;
    if (nums.empty() || !k) return ret;
    deque<int> id;
    for (int i = 0; i < k; ++i) {
        while (id.size() && nums[i] >= nums[id.back()])
            id.pop_back();
        id.push_back(i);
    }
    ret.push_back(nums[id.front()]);
    for (int i = k; i < nums.size(); ++i) {
        while (id.size() && nums[i] >= nums[id.back()])
            id.pop_back();
        id.push_back(i);
        while (id.front() <= i-k)
            id.pop_front();
        ret.push_back(nums[id.front()]);
    }
    return ret;
}

数据流的中位数

priority_queue<int, vector<int>, less<int>> queMin;
priority_queue<int, vector<int>, greater<int>> queMax;
MedianFinder() {}
void addNum(int num) {
    if (queMin.empty() || num <= queMin.top()) {
        queMin.push(num);
        if (queMax.size()+1 < queMin.size()) {
            queMax.push(queMin.top());
            queMin.pop();
        }
    } 
    else {
        queMax.push(num);
        if (queMax.size() > queMin.size()) {
            queMin.push(queMax.top());
            queMax.pop();
        }
    }
}
double findMedian() {
    if (queMin.size() > queMax.size())
        return queMin.top();
    return (queMin.top()+queMax.top()) / 2.0;
}

滑动窗口中位数

priority_queue<long long> small;
priority_queue<long long, vector<long long>, greater<long long>> large;
unordered_map<long long, int> delayed;
long long smallSize, largeSize;
void init() {
    smallSize = largeSize = 0;
}
template<typename T>
void prune(T& heap) {
    while (!heap.empty()) {
        int num = heap.top();
        if (delayed.count(num)) {
            --delayed[num];
            if (!delayed[num])
                delayed.erase(num);
            heap.pop();
        }
        else break;
    }
}
void makeBalance() {
    if (smallSize > largeSize+1) {
        large.push(small.top());
        small.pop();
        --smallSize;
        ++largeSize;
        prune(small);
    }
    else if (smallSize < largeSize) {
        small.push(large.top());
        large.pop();
        ++smallSize;
        --largeSize;
        prune(large);
    }
}
void insert(int num) {
    if (small.empty() || num <= small.top()) {
        small.push(num);
        ++smallSize;
    }
    else {
        large.push(num);
        ++largeSize;
    }
    makeBalance();
}
void erase(int num) {
    ++delayed[num];
    if (num <= small.top()) {
        --smallSize;
        if (num == small.top())
            prune(small);
    }
    else {
        --largeSize;
        if (num == large.top())
            prune(large);
    }
    makeBalance();
}
double getMedian(int k) {
    return k&1 ? small.top() : (small.top()+large.top())/2.0;
}
vector<double> medianSlidingWindow(vector<int>& nums, int k) {
    vector<double> ans;
    if (nums.empty() || !k) return ans;
    init();
    for (int i = 0; i < k; ++i)
        insert(nums[i]);
    ans.push_back(getMedian(k));
    for (int i = k; i < nums.size(); ++i) {
        insert(nums[i]);
        erase(nums[i-k]);
        ans.push_back(getMedian(k));
    }
    return ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值