Fixed Sliding Window: Rethinking the Pattern
You do not have to start at 0, and your loop variable does not need to touch every element.
Thatβs where the sliding window starts to make sense.
π§± The Setupβ
Given:
arr = [2, 1, 5, 1, 3, 2]
k = 3
Goal: iterate over every contiguous window of size N in a clean, readable, bounded way.
π§ͺ Version 1: The Common Approach (Textbook/Tutorial)β
def explore_sliding_window_chatgpt(arr, windowSize):
left = 0
for right in range(len(arr)):
if right - left + 1 == windowSize:
window = arr[left:right + 1]
print(f"Window [{left}:{right}] =>", window)
left += 1
β Works, but...
- Youβre looping from 0, and guarding with
if
- You check the window length every time
- You slide
left
only when the window is valid
I would NEVER be able to write this from scratch... honestly I can barely even read it. There's too much cognitive load.
π Meta Observationsβ
β
"We're iterating a non-loop variable (left
) only inside a condition"β
- That variable (
left
) is part of the condition that guards the loop - This is a feedback loop, not a pure iteration
β "Our loop bounds are immediately protected"β
- The outer loop can go longer (e.g.
len(arr) + 1
) - But slicing behavior and guard conditions protect us from going out of bounds
π§ͺ Version 2: Cleaned Up a Bitβ
Start with an invalid state. Let it become valid naturally.
def explore_sliding_window_cleaning_up_thinking(arr, windowSize):
left = 0 - windowSize # the window is fixed, so lets just "set" it now
for right in range(len(arr)):
left += 1
if left < 0:
continue
print("window", arr[left:right + 1])
Highlights:
- Starts
left
as out of bounds - No window size condition β it's baked into when
left
becomes valid - Cleaner and intuitive
Name: Progressive Guarded Window
β Final Form: The Cleanest (Start Valid)β
You donβt need to arrive at a valid state β you can start there.
def explore_sliding_window_cleaning_up_2(arr, windowSize):
left = 0
for right in range(windowSize - 1, len(arr)):
print("window", arr[left:right + 1])
left += 1
- No conditionals
- Starts
right
at the first index that gives a full window - Slides cleanly by incrementing both
left
andright
This is the most readable, bounded, and semantically aligned version.
βοΈ Python Quirksβ
- Slices are [inclusive:exclusive]
- That means
arr[3:6]
gets you elements3, 4, 5
- This feels wrong if youβre an inclusive-index thinker
So fix it:
def inclusive_slice(arr, start, end):
return arr[start:end + 1]
Use when you want to reason like:
"Give me all values from index A through index B (inclusive)"
π Iteration Patterns Takeawayβ
- You can start anywhere β not just at index 0
- You donβt need to βtouchβ every index
- Think in terms of:
- When is a window valid?
- What indices are needed?
- What constraint defines the window?
Once you do that, all the off-by-one noise disappears. (except python inclusive/exclusive slices lol)
π TL;DRβ
Sliding window isn't about two pointers β it's about controlling a range.
Once the window length is fixed, the simplest form is to start at the first valid position and iterate forward.
left = 0
for right in range(windowSize - 1, len(arr)):
window = arr[left:right + 1]
left += 1
Thatβs it.
And if you really want to prioritize readability, then you can always pull things out further:
left = 0
firstValidRight = windowSize - 1
for right in range(firstValidRight, len(arr)):
window = arr[left:right + 1]
left += 1