🧠
Using Max-Heap (Priority Queue)
💡 This approach improves over brute force by using a max-heap to track the maximum in the current window, but still has overhead due to heap operations.
Intuition
Maintain a max-heap of elements in the current window. Remove elements that fall out of the window and peek the max at each step.
Algorithm
- Initialize a max-heap and a result list.
- Add first k elements to the heap.
- For each window starting from index k, remove elements outside the window from the heap.
- Add the current max (heap top) to the result.
- Slide the window by adding the new element and removing the old one.
- Return the result list.
💡 This approach uses a data structure to avoid scanning the entire window each time but requires careful removal of outdated elements.
from typing import List
import heapq
def maxSlidingWindow(nums: List[int], k: int) -> List[int]:
n = len(nums)
result = []
# Python heapq is min-heap, so store negative values for max-heap
heap = []
for i in range(k):
heapq.heappush(heap, (-nums[i], i))
result.append(-heap[0][0])
for i in range(k, n):
heapq.heappush(heap, (-nums[i], i))
# Remove elements outside the window
while heap[0][1] <= i - k:
heapq.heappop(heap)
result.append(-heap[0][0])
return result
# Example usage
if __name__ == '__main__':
print(maxSlidingWindow([1,3,-1,-3,5,3,6,7], 3))
Line Notes
heap = []Initialize empty heap to store elements with indices for efficient max retrieval
heapq.heappush(heap, (-nums[i], i))Push negative value to simulate max-heap and store index for window tracking
while heap[0][1] <= i - k:Remove elements outside the current window to keep heap valid
result.append(-heap[0][0])Append current max (negated back) to result to build output
import java.util.*;
public class SlidingWindowMaximum {
public static int[] maxSlidingWindow(int[] nums, int k) {
int n = nums.length;
int[] result = new int[n - k + 1];
PriorityQueue<int[]> maxHeap = new PriorityQueue<>((a,b) -> b[0] - a[0]);
for (int i = 0; i < k; i++) {
maxHeap.offer(new int[]{nums[i], i});
}
result[0] = maxHeap.peek()[0];
for (int i = k; i < n; i++) {
maxHeap.offer(new int[]{nums[i], i});
while (maxHeap.peek()[1] <= i - k) {
maxHeap.poll();
}
result[i - k + 1] = maxHeap.peek()[0];
}
return result;
}
public static void main(String[] args) {
int[] res = maxSlidingWindow(new int[]{1,3,-1,-3,5,3,6,7}, 3);
System.out.println(Arrays.toString(res));
}
}
Line Notes
PriorityQueue<int[]> maxHeap = new PriorityQueue<>((a,b) -> b[0] - a[0]);Create max-heap based on element values for efficient max retrieval
maxHeap.offer(new int[]{nums[i], i});Add element and its index to heap to track window elements
while (maxHeap.peek()[1] <= i - k) {Remove elements outside the current window to maintain correctness
result[i - k + 1] = maxHeap.peek()[0];Record current max from heap top to build output
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
int n = nums.size();
vector<int> result;
priority_queue<pair<int,int>> maxHeap; // stores (value, index)
for (int i = 0; i < k; i++) {
maxHeap.push({nums[i], i});
}
result.push_back(maxHeap.top().first);
for (int i = k; i < n; i++) {
maxHeap.push({nums[i], i});
while (maxHeap.top().second <= i - k) {
maxHeap.pop();
}
result.push_back(maxHeap.top().first);
}
return result;
}
int main() {
vector<int> nums = {1,3,-1,-3,5,3,6,7};
int k = 3;
vector<int> res = maxSlidingWindow(nums, k);
for (int val : res) cout << val << " ";
cout << endl;
return 0;
}
Line Notes
priority_queue<pair<int,int>> maxHeap;Max-heap storing (value, index) pairs for efficient max retrieval
maxHeap.push({nums[i], i});Add current element with index to heap to track window elements
while (maxHeap.top().second <= i - k) {Remove elements outside the sliding window to maintain correctness
result.push_back(maxHeap.top().first);Add current max to result to build output
class MaxHeap {
constructor() {
this.heap = [];
}
parent(i) { return Math.floor((i - 1) / 2); }
left(i) { return 2 * i + 1; }
right(i) { return 2 * i + 2; }
swap(i, j) { [this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]]; }
push(val) {
this.heap.push(val);
this.bubbleUp(this.heap.length - 1);
}
bubbleUp(i) {
while (i > 0 && this.heap[this.parent(i)][0] < this.heap[i][0]) {
this.swap(i, this.parent(i));
i = this.parent(i);
}
}
pop() {
if (this.heap.length === 1) return this.heap.pop();
const top = this.heap[0];
this.heap[0] = this.heap.pop();
this.bubbleDown(0);
return top;
}
bubbleDown(i) {
let largest = i;
const left = this.left(i);
const right = this.right(i);
if (left < this.heap.length && this.heap[left][0] > this.heap[largest][0]) largest = left;
if (right < this.heap.length && this.heap[right][0] > this.heap[largest][0]) largest = right;
if (largest !== i) {
this.swap(i, largest);
this.bubbleDown(largest);
}
}
top() {
return this.heap[0];
}
}
function maxSlidingWindow(nums, k) {
const n = nums.length;
const maxHeap = new MaxHeap();
const result = [];
for (let i = 0; i < k; i++) {
maxHeap.push([nums[i], i]);
}
result.push(maxHeap.top()[0]);
for (let i = k; i < n; i++) {
maxHeap.push([nums[i], i]);
while (maxHeap.top()[1] <= i - k) {
maxHeap.pop();
}
result.push(maxHeap.top()[0]);
}
return result;
}
// Example usage
console.log(maxSlidingWindow([1,3,-1,-3,5,3,6,7], 3));
Line Notes
class MaxHeap {Custom max-heap implementation to support element removal and max retrieval
maxHeap.push([nums[i], i]);Add element and index to heap to track window elements
while (maxHeap.top()[1] <= i - k) {Remove elements outside the current window to maintain correctness
result.push(maxHeap.top()[0]);Add current max to result array to build output
TimeO(n log k)
SpaceO(k) amortized
Each insertion and removal from the heap costs O(log k), done n times, resulting in O(n log k) time. Space is O(k) amortized for the heap, as outdated elements are lazily removed.
💡 For n=100,000 and k=1000, this means about 1.5 million operations, which is better but still not optimal.
Interview Verdict: Accepted but slower than optimal
This approach is a good improvement but still not the best; it shows the value of data structures but can be optimized further.