2Brute2Best
🔥0
02

Sliding median (Two Heaps Sub-pattern)

Running median plus removals: as the window slides, one number enters and one leaves.

Signals in the problem statement
  • ›

    "median of each window of size k"

What makes it different

The only new part is removing the leaving number. Heaps can't do that directly, so use lazy deletion (a delayed count map, pruned when a stale number reaches a top) or replace both heaps with two multisets. Values reach ±2³¹ − 1, so average them as doubles.

Questions

ordered from “learn the idea” to “recognise it without help”
  1. 1
    Sliding Window Median
    Interview-Level·LeetCode #480
    Hard

Template

sliding-median-template.cpp
// Sliding window median with two heaps and lazy deletion.
vector<double> medianSlidingWindow(vector<int>& nums, int k) {
    priority_queue<int> low;                                // smaller half
    priority_queue<int, vector<int>, greater<int>> high;   // larger half
    unordered_map<int, int> delayed;                        // value -> copies waiting to be removed
    int lowSize = 0, highSize = 0;                          // LIVE counts only
    auto prune = [&](auto& h) {                             // drop stale tops
        while (!h.empty() && delayed.count(h.top())) {
            if (--delayed[h.top()] == 0) delayed.erase(h.top());
            h.pop();
        }
    };
    auto rebalance = [&]() {                                // low has the same size or one more
        if (lowSize > highSize + 1) {
            high.push(low.top()); low.pop(); lowSize--; highSize++; prune(low);
        } else if (lowSize < highSize) {
            low.push(high.top()); high.pop(); highSize--; lowSize++; prune(high);
        }
    };
    vector<double> res;
    for (int i = 0; i < (int)nums.size(); i++) {
        int x = nums[i];
        if (low.empty() || x <= low.top()) { low.push(x); lowSize++; }
        else { high.push(x); highSize++; }
        if (i >= k) {                                       // nums[i-k] leaves the window
            int gone = nums[i - k];
            delayed[gone]++;
            if (gone <= low.top()) { lowSize--; if (gone == low.top()) prune(low); }
            else { highSize--; if (gone == high.top()) prune(high); }
        }
        rebalance();
        if (i >= k - 1)
            res.push_back(k % 2 ? (double)low.top() : ((double)low.top() + high.top()) / 2.0);
    }
    return res;
}
Remember this · Two Heaps
Trigger
Running median, sliding median, choosing from two pools (available vs locked).
Think
Can I split the data into two halves and only care about the boundary between them?
Key question
How do I rebalance so the sizes differ by at most one?