Sliding Window
Optimize subarray/substring problems
Sliding Window Technique
The sliding window technique converts brute-force O(n²) subarray/substring problems to O(n). It uses two pointers (left, right) to maintain a 'window' of elements, expanding right and shrinking left based on conditions.
Sliding Window Pattern
typescript
// Sliding Window Problems
// Maximum sum subarray of size k
function maxSumSubarray(arr: number[], k: number): number {
let sum = 0, maxSum = -Infinity;
for (let i = 0; i < arr.length; i++) {
sum += arr[i];
if (i >= k) sum -= arr[i - k];
if (i >= k - 1) maxSum = Math.max(maxSum, sum);
}
return maxSum;
}
// Longest substring without repeating characters
function lengthOfLongestSubstring(s: string): number {
const seen = new Map<string, number>();
let maxLen = 0, left = 0;
for (let right = 0; right < s.length; right++) {
if (seen.has(s[right]) && seen.get(s[right])! >= left) {
left = seen.get(s[right])! + 1;
}
seen.set(s[right], right);
maxLen = Math.max(maxLen, right - left + 1);
}
return maxLen;
}
// Minimum window substring
function minWindow(s: string, t: string): string {
const need = new Map<string, number>();
for (const c of t) need.set(c, (need.get(c) || 0) + 1);
let have = 0, required = need.size;
let left = 0, minLen = Infinity, result = '';
const window = new Map<string, number>();
for (let right = 0; right < s.length; right++) {
const c = s[right];
window.set(c, (window.get(c) || 0) + 1);
if (need.has(c) && window.get(c) === need.get(c)) have++;
while (have === required) {
if (right - left + 1 < minLen) {
minLen = right - left + 1;
result = s.slice(left, right + 1);
}
const d = s[left++];
window.set(d, window.get(d)! - 1);
if (need.has(d) && window.get(d)! < need.get(d)!) have--;
}
}
return result;
}