The Sliding Window technique uses a window that can expand or contract to efficiently solve substring and subarray problems.
- Substring problems - Find longest/shortest substring satisfying conditions
- Subarray problems - Find subarray with sum/product equal to target
- Fixed size problems - Find subarray with fixed size
- Variable size problems - Find subarray with variable size
Used for finding the smallest/largest window satisfying a condition.
graph TD
A[Start: left=0, right=0] --> B{right < size?}
B -- No --> C[End]
B -- Yes --> D[Add nums[right] to Window]
D --> E{Condition Violated?}
E -- Yes --> F[Remove nums[left]]
F --> G[left++]
G --> E
E -- No --> H[Update Result]
H --> I[right++]
I --> B
| Window Type | Constraint | Logic | Example |
|---|---|---|---|
| Fixed Size | window.size == k |
add(right), remove(right-k) |
Max Sum Subarray of size K |
| Variable (Min) | sum >= target |
expand until valid, then shrink |
Min Subarray Len |
| Variable (Max) | distinct <= k |
expand, if invalid shrink |
Longest Substring |
// Find subarray of size k with maximum sum
int maxSumFixedWindow(vector<int>& nums, int k) {
if (nums.size() < k) return 0;
// Calculate sum of first window
int windowSum = 0;
for (int i = 0; i < k; i++) {
windowSum += nums[i];
}
int maxSum = windowSum;
// Slide the window
for (int i = k; i < nums.size(); i++) {
windowSum = windowSum - nums[i - k] + nums[i];
maxSum = max(maxSum, windowSum);
}
return maxSum;
}Time Complexity: O(n)
Space Complexity: O(1)
// Find shortest subarray with sum >= target
int minSubArrayLen(int target, vector<int>& nums) {
int left = 0, right = 0;
int windowSum = 0;
int minLen = INT_MAX;
while (right < nums.size()) {
windowSum += nums[right];
// Contract window when condition is met
while (windowSum >= target) {
minLen = min(minLen, right - left + 1);
windowSum -= nums[left];
left++;
}
right++;
}
return minLen == INT_MAX ? 0 : minLen;
}Time Complexity: O(n)
Space Complexity: O(1)
// Find longest substring without repeating characters
int lengthOfLongestSubstring(string s) {
vector<int> charIndex(128, -1);
int left = 0, maxLen = 0;
for (int right = 0; right < s.length(); right++) {
char currentChar = s[right];
// If character already appeared, update left
if (charIndex[currentChar] >= left) {
left = charIndex[currentChar] + 1;
}
charIndex[currentChar] = right;
maxLen = max(maxLen, right - left + 1);
}
return maxLen;
}Time Complexity: O(n)
Space Complexity: O(1) - Fixed size array
- 209. Minimum Size Subarray Sum
- 3. Longest Substring Without Repeating Characters
- 424. Longest Repeating Character Replacement
// Expand window when need to add elements
while (right < nums.size() && !condition_met) {
windowSum += nums[right];
right++;
}
// Contract window when condition is met
while (left < right && condition_met) {
windowSum -= nums[left];
left++;
}// Use hash map to count characters in window
unordered_map<char, int> charCount;
int uniqueChars = 0;
// Add new character
if (++charCount[s[right]] == 1) uniqueChars++;
// Remove old character
if (--charCount[s[left]] == 0) uniqueChars--;// Use deque to find max/min in window
deque<int> dq; // Monotonic decreasing
// Add new element
while (!dq.empty() && nums[dq.back()] < nums[right]) {
dq.pop_back();
}
dq.push_back(right);
// Remove old element
if (dq.front() <= right - k) {
dq.pop_front();
}// Modern C++23 approach with ranges and views
auto slidingWindow = [&](int k) -> std::vector<int> {
std::vector<int> result;
// Create view for first window
auto firstWindow = nums | std::views::take(k);
int windowSum = std::ranges::fold_left(firstWindow, 0, std::plus{});
result.push_back(windowSum);
// Slide the window
for (int i = k; i < std::ranges::ssize(nums); ++i) {
windowSum = windowSum - nums[i - k] + nums[i];
result.push_back(windowSum);
}
return result;
};// Calculate sum of windows with std::views
auto windowSums = std::views::iota(0, static_cast<int>(nums.size()) - k + 1)
| std::views::transform([&](int start) {
auto window = nums | std::views::drop(start) | std::views::take(k);
return std::ranges::fold_left(window, 0, std::plus{});
});| Pattern | Time | Space | Best For |
|---|---|---|---|
| Fixed Size | O(n) | O(1) | Subarray with fixed size |
| Variable Size | O(n) | O(1) | Subarray with specific conditions |
| Character Count | O(n) | O(k) | String problems with characters |
- Minimum Size Subarray Sum
- Longest Substring Without Repeating Characters
- Longest Repeating Character Replacement
- Two Pointers - Foundation of Sliding Window
- Hash Map - Count and track elements
- Monotonic Queue/Stack - Optimize max/min
- Binary Search - Find optimal window size
// Stop early when result is found
if (maxLen == targetLength) break;// Use vector instead of unordered_map for ASCII
vector<int> charCount(128, 0);// Handle edge cases
if (nums.empty() || k <= 0) return 0;
if (k > nums.size()) return -1; // or handle appropriatelyRemember: Sliding Window is a powerful pattern for substring/subarray problems. Practice to master it! 🚀