For every possible window of size k, we simply look at all k elements and pick the maximum.
We slide the window one step at a time, and each time we scan all elements inside it to find the max.
This method is very easy to understand but slow, because we repeatedly re-scan many of the same elements.
output to store the maximum of each window.i from 0 to len(nums) - k:maxi to nums[i].i to i + k - 1 and update maxi.maxi to output.output after checking all windows.class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
output = []
for i in range(len(nums) - k + 1):
maxi = nums[i]
for j in range(i, i + k):
maxi = max(maxi, nums[j])
output.append(maxi)
return outputWhere is the length of the array and is the size of the window.
The brute-force solution recomputes the maximum for every window by scanning all k elements each time, which is slow.
A Segment Tree helps us answer “what is the maximum in this range?” much faster after some preprocessing.
Think of the segment tree as a special structure built on top of the array where:
Once we build this tree:
[L, R] (our sliding window) in O(log n) time.So the process is:
build once → query many times efficiently.
Build the Segment Tree
tree big enough to store a full binary tree.tree).tree[1] (the root) holds the maximum of the entire array.Range Maximum Query (Segment Tree query(l, r)):
l and r to point to the leaves representing those indices.l <= r in the tree:l is a right child, consider tree[l] in the answer and move l to the next segment.r is a left child, consider tree[r] in the answer and move r to the previous segment.l and r up one level by dividing by 2.Sliding Window using the Segment Tree
i (from 0 to n - k):[i, i + k - 1].Return the output list containing the maximum for each sliding window.
class SegmentTree:
def __init__(self, N, A):
self.n = N
while (self.n & (self.n - 1)) != 0:
self.n += 1
self.build(N, A)
def build(self, N, A):
self.tree = [float('-inf')] * (2 * self.n)
for i in range(N):
self.tree[self.n + i] = A[i]
for i in range(self.n - 1, 0, -1):
self.tree[i] = max(self.tree[i << 1], self.tree[i << 1 | 1])
def query(self, l, r):
res = float('-inf')
l += self.n
r += self.n + 1
while l < r:
if l & 1:
res = max(res, self.tree[l])
l += 1
if r & 1:
r -= 1
res = max(res, self.tree[r])
l >>= 1
r >>= 1
return res
class Solution:
def maxSlidingWindow(self, nums, k):
n = len(nums)
segTree = SegmentTree(n, nums)
output = []
for i in range(n - k + 1):
output.append(segTree.query(i, i + k - 1))
return outputWe want to quickly get the maximum value inside a sliding window that moves across the array.
A max-heap is perfect for this because it always lets us access the largest element instantly.
As we slide the window:
This way, we efficiently maintain the maximum even as the window moves.
(value, index) for all elements we encounter.k:class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
heap = []
output = []
for i in range(len(nums)):
heapq.heappush(heap, (-nums[i], i))
if i >= k - 1:
while heap[0][1] <= i - k:
heapq.heappop(heap)
output.append(-heap[0][0])
return outputInstead of recalculating the maximum for each sliding window, we can preprocess the array so that every window’s maximum can be answered in O(1) time.
We divide the array into blocks of size k.
Within each block, we build:
For any sliding window:
rightMax[i]leftMax[i + k - 1]The true window maximum is the larger of those two.
This lets us compute each window's maximum instantly.
k.leftMax array:rightMax array:k:max(rightMax[window_start], leftMax[window_end]).class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
n = len(nums)
leftMax = [0] * n
rightMax = [0] * n
leftMax[0] = nums[0]
rightMax[n - 1] = nums[n - 1]
for i in range(1, n):
if i % k == 0:
leftMax[i] = nums[i]
else:
leftMax[i] = max(leftMax[i - 1], nums[i])
if (n - 1 - i) % k == 0:
rightMax[n - 1 - i] = nums[n - 1 - i]
else:
rightMax[n - 1 - i] = max(rightMax[n - i], nums[n - 1 - i])
output = [0] * (n - k + 1)
for i in range(n - k + 1):
output[i] = max(leftMax[i + k - 1], rightMax[i])
return outputA deque helps us efficiently track the maximum inside the sliding window.
The key idea is to keep the deque storing indices of elements in decreasing order of their values.
This guarantees that:
By maintaining this structure, each element is added and removed at most once, giving an optimal solution.
k, the front of the deque represents the maximum — add it to the output.class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
output = []
q = deque() # index
l = r = 0
while r < len(nums):
while q and nums[q[-1]] < nums[r]:
q.pop()
q.append(r)
if l > q[0]:
q.popleft()
if (r + 1) >= k:
output.append(nums[q[0]])
l += 1
r += 1
return output