Recommended resources
The freely available resources this lesson will direct you to.
Welcome to your second lesson. In our previous session, we established a strong foundation with the two-pointer technique, particularly the "same direction" variant where two pointers traverse an array together. Today, we'll build directly on that concept to explore one of the most powerful and frequently tested algorithmic patterns in software engineering interviews: the sliding window.
This pattern is essential for your goal of preparing for senior backend roles. It's a method for transforming inefficient, brute-force solutions for subarray or substring problems into highly optimized, linear-time solutions. In this lesson, we will deconstruct the sliding window pattern, learn to identify when to use it, and apply it to both fixed-size and variable-size window problems.
The Core Idea: An Efficient Moving View
Imagine you have a long array and need to find a contiguous block of elements (a subarray) that has a specific property. The naive way is to check every single possible subarray, which often involves nested loops and leads to an or worse time complexity.
The sliding window pattern reframes this. Instead of generating each subarray from scratch, we maintain a single "window" and slide it across the array. The key insight is that as the window slides, we don't need to re-process the entire new window. We can achieve a significant performance gain by simply updating our calculations based on the element that enters the window and the one that leaves it.

This clever update mechanism is why sliding window algorithms typically run in linear time, , as each element is visited by the window's start and end pointers at most once.
A fantastic article by "labuladong" presents a universal code framework for this pattern. Let's start by reading the overview to internalize the general structure.
Sliding Window Algorithm Code Template - Labuladong Algo Notes
This reading introduces the core logic of the sliding window and presents a pseudocode framework that serves as a template for a wide range of problems. It also explains why the time complexity is O(N) despite the nested loops.
Please read the first part of the article, from the beginning down to the pseudocode framework. Pay close attention to the explanation of why the complexity is linear and the final pseudocode template. This template is the theoretical backbone for the rest of the lesson.
The article you just reviewed introduces the two pointers, left and right, that define the boundaries of our window. We will now see how this plays out in two major variations of the pattern.
Pattern 1: Fixed-Size Sliding Window
The simplest application of the sliding window is when the window size is fixed. These problems often ask for a property of all subarrays of a specific length, k.
A classic example is: Find the maximum sum of any contiguous subarray of size k.
A naive solution would be:
- Iterate through the array from the start to the
n-k-th element (this marks the start of each possible window). - For each starting position, loop through the next
kelements to calculate their sum. - Keep track of the maximum sum found.
This approach has a time complexity of , which can be too slow ifkis large.
The sliding window approach optimizes this to :
- Calculate the sum of the first window of size
k. This is your initialmax_sum. - Iterate from the
k-th element to the end of the array. In each step:- Add the new element (the one entering the window on the right) to the current sum.
- Subtract the old element (the one leaving the window on the left) from the current sum.
- Update
max_sumwith the new current sum if it's larger.
This video from freeCodeCamp provides an excellent, detailed walkthrough of this exact problem, comparing the naive and optimized approaches.
Sliding Window Algorithm for Tech Interviews - Full Course
This segment of the video explains and visualizes the fixed-size sliding window pattern using the "maximum subarray sum of size K" problem.
Watch the section from the problem description to the end of the naive approach's complexity analysis. Then, continue from the optimized algorithm explanation to its complexity analysis. Notice how the logic of subtracting the trailing element and adding the leading element reduces the work done at each step to a constant amount.
Since your primary language is Go, this article from Habr provides a nice implementation for a similar fixed-size window problem. It shows the clear evolution from a quadratic-time brute-force solution to a linear-time sliding window solution.
Algorithms in Go: Sliding Window Pattern / Habr
This article applies the sliding window pattern to a problem in Go, which should be very familiar to you. It starts with a naive approach and refines it.
Read from the beginning, where it introduces the problem. Skim the brute-force implementation, and then focus on the section "Can we do better than that?". Study the optimized Go code and the explanation of how it achieves linear time.
Pattern 2: Variable-Size Sliding Window
Things get more interesting when the window size isn't fixed. In these problems, the window expands and shrinks dynamically based on a certain condition. They are often phrased as finding the "longest," "shortest," or "first" subarray/substring that satisfies a property.
The general strategy, as outlined in the labuladong article, is:
- Expand the window by incrementing the
rightpointer. Update any data structures tracking the window's state. - Once a certain condition is violated (e.g., a sum exceeds a target, a character is repeated), enter a loop to shrink the window from the left by incrementing the
leftpointer until the condition is met again. - Update the answer during either the expansion or shrinkage phase, depending on the problem.
A quintessential example is: Find the length of the longest substring without repeating characters.
Here, the window expands as long as it encounters new, unique characters. The moment a duplicate character is added, the window is invalid. To fix this, we must shrink the window from the left until the duplicate is removed.
The labuladong article provides a perfect walkthrough for this problem, applying the general framework.
Sliding Window Algorithm Code Template - Labuladong Algo Notes
This section applies the general sliding window template to a classic variable-size window problem.
Read the section on "Longest Substring Without Repeating Characters". Pay attention to how the condition for shrinking the window is defined: while (window.get(c) > 1). Also, note when the result is updated.
To see this in action, the freeCodeCamp video offers another great visual explanation.
Sliding Window Algorithm for Tech Interviews - Full Course
This video segment provides an animated approach to solving the "longest unique substring" problem using a variable-size window.
Watch the section from the problem approach to the end of the complexity analysis. This will visually reinforce how the window grows and shrinks in response to the "uniqueness" constraint.
Here's how you might implement this in Go. We use a map to keep track of the character counts within the current window.
package main
import "fmt"
func lengthOfLongestSubstring(s string) int {
// A map to store the frequency of characters in the current window.
windowCounts := make(map[byte]int)
left := 0
maxLength := 0
for right := 0; right < len(s); right++ {
// Add the new character to the window.
rightChar := s[right]
windowCounts[rightChar]++
// If the character count becomes > 1, it's a duplicate.
// Shrink the window from the left until the window is valid again.
for windowCounts[rightChar] > 1 {
leftChar := s[left]
windowCounts[leftChar]--
left++
}
// After ensuring the window is valid, update the max length.
// The current window length is right - left + 1.
if (right - left + 1) > maxLength {
maxLength = right - left + 1
}
}
return maxLength
}
func main() {
fmt.Println(lengthOfLongestSubstring("abcabcbb")) // Output: 3
fmt.Println(lengthOfLongestSubstring("pwwkew")) // Output: 3
}
This Go implementation directly mirrors the logic we've discussed: an outer loop expands the window, and an inner while loop contracts it when a duplicate is found. This expand/contract dynamic is the heart of the variable-size window pattern.
A General Recipe for Sliding Window Problems
As you prepare for interviews, it's helpful to have a mental checklist. The labuladong article provided a great one. To solve almost any sliding window problem, you need to answer three questions:
- When do you expand the window? (Usually, this is done in every step of the main loop by moving
right.) What data do you update when a character enters? - When do you shrink the window? (This is the crucial conditional logic.) What defines an "invalid" window that needs shrinking? What data do you update when a character leaves?
- When do you update the final answer? (For "max" problems, it's often after each valid state. for "min" problems, it's often right after you find a valid window and before you shrink it).
Mastering the answers to these three questions for different problem variations will make you proficient with this pattern.
Conclusion
In this lesson, we've taken a deep dive into the sliding window pattern, a crucial optimization technique for subarray and substring problems. You've learned how it builds upon the two-pointer concept to achieve linear time complexity.
Key Takeaways:
- The sliding window pattern avoids redundant computations by intelligently updating a window's state as it moves, rather than recalculating from scratch. This reduces time complexity from polynomial to linear.
- Fixed-size windows are simpler: the window moves one step at a time, and you update a value (like a sum) by subtracting the leaving element and adding the entering one.
- Variable-size windows are more dynamic: the window expands (
rightpointer moves) and shrinks (leftpointer moves) based on whether a specific condition is met or violated. - Data structures like hash maps are essential for efficiently tracking the state of the window (e.g., character counts).
In our next lesson, we'll focus explicitly on hash maps. We've already seen their power today, and a deeper understanding will unlock solutions to a whole new class of lookup-heavy problems that are also very common in interviews.