This page documents the Sliding Window Pattern, a technique for efficiently processing contiguous subsequences (subarrays or substrings) by maintaining a dynamic window with two pointers. The pattern is demonstrated through Problem 0003 (Longest Substring Without Repeating Characters), which finds the maximum-length substring with all unique characters.
For other algorithmic patterns, see Hash Table Pattern, Two Pointers Pattern, and Binary Search Pattern.
The sliding window pattern uses two pointers (l and r) to define a window range [l, r] within a sequence. The window expands by moving the right pointer forward and contracts by moving the left pointer forward, maintaining a specific invariant throughout the process.
Common Use Cases:
Key Characteristics:
| Aspect | Description |
|---|---|
| Pointers | Two pointers l (left) and r (right) defining window boundaries |
| Window Invariant | A condition that must always hold true within [l, r] |
| Expansion | Right pointer r moves forward to include new elements |
| Contraction | Left pointer l moves forward to restore the invariant |
| Time Complexity | Typically O(n) since each element is visited at most twice |
Sources: solution/0000-0099/0003.Longest Substring Without Repeating Characters/README.md65-73 solution/0000-0099/0003.Longest Substring Without Repeating Characters/README_EN.md64-71
Algorithm Steps:
l=0 and r=0, and a frequency counter cntr and updating cnt[s[r]]cnt[s[r]] > 1, the window has duplicatesl and decrementing cnt[s[l]] until the invariant is restoredr - l + 1r reaches the end of the sequenceSources: solution/0000-0099/0003.Longest Substring Without Repeating Characters/README.md65-71 solution/0000-0099/0003.Longest Substring Without Repeating Characters/README_EN.md64-69
Problem: Longest Substring Without Repeating Characters
Given a string s, find the length of the longest substring without repeating characters.
Examples:
| Input | Output | Explanation |
|---|---|---|
"abcabcbb" | 3 | Substring "abc" has length 3 |
"bbbbb" | 1 | Substring "b" has length 1 |
"pwwkew" | 3 | Substring "wke" has length 3 |
Constraints:
0 <= s.length <= 5 * 10^4Sources: solution/0000-0099/0003.Longest Substring Without Repeating Characters/README.md17-58 solution/0000-0099/0003.Longest Substring Without Repeating Characters/README_EN.md17-55
Sources: solution/0000-0099/0003.Longest Substring Without Repeating Characters/README.md67-70
The sliding window pattern for problem 0003 uses the following key data structures:
| Component | Type | Purpose | Implementation |
|---|---|---|---|
cnt | Array or Hash Map | Frequency counter for characters in window | int[128] for ASCII or Map<char, int> |
l | Integer | Left boundary of window | Initialized to 0 |
r | Integer | Right boundary of window | Incremented in loop |
ans | Integer | Maximum window size found | Updated with max(ans, r - l + 1) |
Array vs Hash Map:
int[128]): Used when character set is bounded (ASCII), provides O(1) accessSources: solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.java3-4 solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.ts3
Pointer Movement Rules:
r: Always increments in the main loop, adding new elementsl: Increments conditionally in the inner while loop when invariant is violatedr - l + 1 after each expansionSources: solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.py4-10 solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.java5-11
The Python solution uses Counter from collections for frequency tracking:
cnt = Counter()
ans = l = 0
for r, c in enumerate(s):
cnt[c] += 1
while cnt[c] > 1:
cnt[s[l]] -= 1
l += 1
ans = max(ans, r - l + 1)
Key Functions:
enumerate(s): Returns (index, character) pairs for iterationCounter(): Hash map for character frequenciesmax(ans, r - l + 1): Updates maximum window sizeSources: solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.py1-11
The Java solution uses a fixed-size array for ASCII characters:
int[] cnt = new int[128];
for (int l = 0, r = 0; r < n; ++r) {
char c = s.charAt(r);
++cnt[c];
while (cnt[c] > 1) {
--cnt[s.charAt(l++)];
}
ans = Math.max(ans, r - l + 1);
}
Key Functions:
s.charAt(r): Accesses character at index rcnt[c]: Direct array indexing using character as indexl++: Post-increment within array access s.charAt(l++)Sources: solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.java1-15
The C++ solution uses stack-allocated array for efficiency:
int cnt[128]{};
for (int l = 0, r = 0; r < n; ++r) {
++cnt[s[r]];
while (cnt[s[r]] > 1) {
--cnt[s[l++]];
}
ans = max(ans, r - l + 1);
}
Key Features:
int cnt[128]{}: Zero-initialized array on stacks[r]: Direct string indexing (C++ strings support operator[])max(ans, r - l + 1): STL algorithm for maximumSources: solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.cpp1-15
The TypeScript solution uses Map for type-safe frequency tracking:
const cnt = new Map<string, number>();
for (let l = 0, r = 0; r < n; ++r) {
cnt.set(s[r], (cnt.get(s[r]) || 0) + 1);
while (cnt.get(s[r])! > 1) {
cnt.set(s[l], cnt.get(s[l])! - 1);
++l;
}
ans = Math.max(ans, r - l + 1);
}
Key Functions:
Map<string, number>: Type-safe hash mapcnt.get(s[r]) || 0: Returns 0 if key doesn't existcnt.get(s[r])!: Non-null assertion operatorSources: solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.ts1-14
| Language | Counter Type | Space | Iteration | Notes |
|---|---|---|---|---|
| Python | Counter() | O(Σ) | enumerate(s) | Dynamic hash map, clean syntax |
| Java | int[128] | O(1) | for (l=0, r=0; ...) | Fixed array, fastest for ASCII |
| C++ | int cnt[128]{} | O(1) | for (l=0, r=0; ...) | Stack-allocated, zero-initialized |
| TypeScript | Map<string, number> | O(Σ) | for (let l=0, r=0; ...) | Type-safe, flexible |
| Go | [128]int{} | O(1) | for r, c := range s | Array literal, range iteration |
| Rust | [0; 128] | O(1) | enumerate() | Array with explicit size |
| C# | int[128] | O(1) | for (l=0, r=0; ...) | Similar to Java |
| PHP | array_fill(0, 128, 0) | O(1) | for ($r=0; ...) | Dynamic array as fixed array |
Sources: solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.py1-11 solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.java1-15 solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.cpp1-15 solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.ts1-14 solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.go1-13
O(n) where n is the length of the string s.
Analysis:
r iterates through the string exactly once: O(n)l also moves at most n times across the entire executionr expanding, once by l contracting)while loop operations are amortized O(1) per characterSources: solution/0000-0099/0003.Longest Substring Without Repeating Characters/README.md73 solution/0000-0099/0003.Longest Substring Without Repeating Characters/README_EN.md71
O(|Σ|) where |Σ| is the size of the character set.
Breakdown:
| Implementation | Space | Explanation |
|---|---|---|
Array-based (int[128]) | O(1) | Fixed size for ASCII character set |
Hash Map-based (Counter, Map) | O(min(n, | Σ |
| Practical | O(128) = O(1) | For ASCII, this is constant |
| General | O( | Σ |
The algorithm ignores the space used by the answer, following the convention that output space is not counted in space complexity analysis.
Sources: solution/0000-0099/0003.Longest Substring Without Repeating Characters/README.md73 solution/0000-0099/0003.Longest Substring Without Repeating Characters/README_EN.md71
The sliding window pattern has several variants depending on the problem requirements:
Problem 0003 Characteristics:
cnt[s[r]] <= 1 (no duplicate characters)rcnt[s[r]] > 1)r - l + 1 across all valid windowsSources: solution/0000-0099/0003.Longest Substring Without Repeating Characters/README.md65-71
Function Signatures:
| Language | Signature |
|---|---|
| Python | def lengthOfLongestSubstring(self, s: str) -> int: |
| Java | public int lengthOfLongestSubstring(String s) |
| C++ | int lengthOfLongestSubstring(string s) |
| TypeScript | function lengthOfLongestSubstring(s: string): number |
| Go | func lengthOfLongestSubstring(s string) (ans int) |
| Rust | pub fn length_of_longest_substring(s: String) -> i32 |
Sources: solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.py2 solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.java2 solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.cpp3 solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.ts1 solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.go1 solution/0000-0099/0003.Longest Substring Without Repeating Characters/Solution.rs2
When to Use Sliding Window:
The sliding window pattern is applicable when a problem exhibits these characteristics:
| Characteristic | Description | Example |
|---|---|---|
| Contiguous subsequence | Problem asks about subarrays/substrings | "Find longest substring..." |
| Optimization goal | Maximize, minimize, or count | "Longest", "shortest", "number of" |
| Window invariant | A clear condition to maintain | "Without repeating characters" |
| Linear scan | Can be solved by scanning once | Each element processed in order |
Problem 0003 Indicators:
Sources: solution/0000-0099/0003.Longest Substring Without Repeating Characters/README.md13-58 solution/0000-0099/0003.Longest Substring Without Repeating Characters/README_EN.md13-55
The sliding window pattern relates to other algorithmic techniques in the repository:
cnt in problem 0003)Difference from Two Pointers:
[l, r]Sources: solution/0000-0099/0003.Longest Substring Without Repeating Characters/README.md5-8
Refresh this wiki
This wiki was recently refreshed. Please wait 2 days to refresh again.