Add sliding-window module: 12 sliding window and two-pointer interview problems, brute-force cross-checks, dry-run traces, operation counts, pitfalls (11 tests)
Co-Authored-By: Claude Sonnet 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_017ic4b6EqSkUWKNBc8i3Q3U
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
Max sum of 3 consecutive elements in [2, 1, 5, 1, 3, 2]
|
||||
=======================================================
|
||||
|
||||
first window [2, 1, 5] sum=8 best=8
|
||||
right=3 +1 -2 window=[1, 5, 1] sum=7 best=8
|
||||
right=4 +3 -1 window=[5, 1, 3] sum=9 best=9
|
||||
right=5 +2 -5 window=[1, 3, 2] sum=6 best=9
|
||||
|
||||
answer = 9
|
||||
@@ -0,0 +1,21 @@
|
||||
Longest substring without repeating characters
|
||||
==============================================
|
||||
|
||||
input "abcabcbb"
|
||||
right=0 'a' left=0 window="a" best=1
|
||||
right=1 'b' left=0 window="ab" best=2
|
||||
right=2 'c' left=0 window="abc" best=3
|
||||
right=3 'a' left=1 window="bca" best=3 seen at 0 inside the window, left 0 -> 1
|
||||
right=4 'b' left=2 window="cab" best=3 seen at 1 inside the window, left 1 -> 2
|
||||
right=5 'c' left=3 window="abc" best=3 seen at 2 inside the window, left 2 -> 3
|
||||
right=6 'b' left=5 window="cb" best=3 seen at 4 inside the window, left 3 -> 5
|
||||
right=7 'b' left=7 window="b" best=3 seen at 6 inside the window, left 5 -> 7
|
||||
answer = 3
|
||||
|
||||
input "abba"
|
||||
right=0 'a' left=0 window="a" best=1
|
||||
right=1 'b' left=0 window="ab" best=2
|
||||
right=2 'b' left=2 window="b" best=2 seen at 1 inside the window, left 0 -> 2
|
||||
right=3 'a' left=2 window="ba" best=2 seen at 0 but that is left of the window, left stays 2
|
||||
answer = 2
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
Minimum window substring: s="ADOBECODEBANC" t="ABC"
|
||||
===================================================
|
||||
|
||||
right=5 'C' window="ADOBEC" is VALID
|
||||
new best "ADOBEC" (length 6)
|
||||
drop 'A' -> window="DOBEC" no longer valid, missing=1
|
||||
right=10 'A' window="DOBECODEBA" is VALID
|
||||
drop 'D' -> window="OBECODEBA" still valid
|
||||
drop 'O' -> window="BECODEBA" still valid
|
||||
drop 'B' -> window="ECODEBA" still valid
|
||||
drop 'E' -> window="CODEBA" still valid
|
||||
drop 'C' -> window="ODEBA" no longer valid, missing=1
|
||||
right=12 'C' window="ODEBANC" is VALID
|
||||
drop 'O' -> window="DEBANC" still valid
|
||||
drop 'D' -> window="EBANC" still valid
|
||||
new best "EBANC" (length 5)
|
||||
drop 'E' -> window="BANC" still valid
|
||||
new best "BANC" (length 4)
|
||||
drop 'B' -> window="ANC" no longer valid, missing=1
|
||||
|
||||
answer = "BANC"
|
||||
@@ -0,0 +1,13 @@
|
||||
Sliding window maximum, k=3, input [1, 3, -1, -3, 5, 3, 6, 7]
|
||||
=============================================================
|
||||
|
||||
right=0 a[right]=1 deque(value@index)=[1@0]
|
||||
right=1 a[right]=3 deque(value@index)=[3@1]
|
||||
right=2 a[right]=-1 deque(value@index)=[3@1, -1@2] -> window max 3
|
||||
right=3 a[right]=-3 deque(value@index)=[3@1, -1@2, -3@3] -> window max 3
|
||||
right=4 a[right]=5 deque(value@index)=[5@4] -> window max 5
|
||||
right=5 a[right]=3 deque(value@index)=[5@4, 3@5] -> window max 5
|
||||
right=6 a[right]=6 deque(value@index)=[6@6] -> window max 6
|
||||
right=7 a[right]=7 deque(value@index)=[7@7] -> window max 7
|
||||
|
||||
answer = [3, 3, 5, 5, 6, 7]
|
||||
@@ -0,0 +1,21 @@
|
||||
Opposite-end two pointers
|
||||
=========================
|
||||
|
||||
Two Sum II: sorted [1, 3, 4, 6, 8, 11], target 10
|
||||
lo=0 hi=5 1 + 11 = 12 > 10 hi--
|
||||
lo=0 hi=4 1 + 8 = 9 < 10 lo++
|
||||
lo=1 hi=4 3 + 8 = 11 > 10 hi--
|
||||
lo=1 hi=3 3 + 6 = 9 < 10 lo++
|
||||
lo=2 hi=3 4 + 6 = 10 == 10 found
|
||||
answer = indices [2, 3]
|
||||
|
||||
Container With Most Water: heights [1, 8, 6, 2, 5, 4, 8, 3, 7]
|
||||
lo=0 hi=8 min(1,7) x 8 = 8 best=8 lo++ (left line is shorter)
|
||||
lo=1 hi=8 min(8,7) x 7 = 49 best=49 hi-- (right line is not taller)
|
||||
lo=1 hi=7 min(8,3) x 6 = 18 best=49 hi-- (right line is not taller)
|
||||
lo=1 hi=6 min(8,8) x 5 = 40 best=49 hi-- (right line is not taller)
|
||||
lo=1 hi=5 min(8,4) x 4 = 16 best=49 hi-- (right line is not taller)
|
||||
lo=1 hi=4 min(8,5) x 3 = 15 best=49 hi-- (right line is not taller)
|
||||
lo=1 hi=3 min(8,2) x 2 = 4 best=49 hi-- (right line is not taller)
|
||||
lo=1 hi=2 min(8,6) x 1 = 6 best=49 hi-- (right line is not taller)
|
||||
answer = 49
|
||||
@@ -0,0 +1,15 @@
|
||||
Twelve problems: optimised answer vs brute-force answer on one example each
|
||||
===========================================================================
|
||||
|
||||
1. maxSumSubarray([2, 1, 5, 1, 3, 2], 3) = 9 brute = 9
|
||||
2. permutationInString("ab", "eidbaooo") = true; ("ab", "eidboaoo") = false brute = true / false
|
||||
3. slidingWindowMaximum([1, 3, -1, -3, 5, 3, 6, 7], 3) = [3, 3, 5, 5, 6, 7]
|
||||
4. longestUniqueSubstring("abcabcbb") = 3 brute = 3
|
||||
5. longestKDistinct("eceba", 2) = 3 brute = 3
|
||||
6. characterReplacement("AABABBA", 1) = 4 brute = 4
|
||||
7. longestOnes([1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 0], 2) = 6 brute = 6
|
||||
8. minSubArrayLen(7, [2, 3, 1, 2, 4, 3]) = 2 brute = 2
|
||||
9. minWindow("ADOBECODEBANC", "ABC") = "BANC"; minWindow("a", "aa") = "" brute = "BANC"
|
||||
10. twoSumSorted([2, 7, 11, 15], 9) = [0, 1]; target 100 = [] (none)
|
||||
11. threeSum([-1, 0, 1, 2, -1, -4]) = [[-1, -1, 2], [-1, 0, 1]]
|
||||
12. maxArea([1, 8, 6, 2, 5, 4, 8, 3, 7]) = 49 brute = 49
|
||||
@@ -0,0 +1,17 @@
|
||||
Randomized agreement with brute force (seed 2026, 2000 cases per problem)
|
||||
=========================================================================
|
||||
|
||||
1. maxSumSubarray 2000 cases, 0 disagreements
|
||||
2. permutationInString 2000 cases, 0 disagreements
|
||||
3. slidingWindowMaximum 2000 cases, 0 disagreements
|
||||
4. longestUniqueSubstring 2000 cases, 0 disagreements
|
||||
5. longestKDistinct 2000 cases, 0 disagreements
|
||||
6. characterReplacement 2000 cases, 0 disagreements
|
||||
7. longestOnes 2000 cases, 0 disagreements
|
||||
8. minSubArrayLen 2000 cases, 0 disagreements
|
||||
9. minWindow 2000 cases, 0 disagreements
|
||||
10. twoSumSorted 2000 cases, 0 disagreements
|
||||
11. threeSum 2000 cases, 0 disagreements
|
||||
12. maxArea 2000 cases, 0 disagreements
|
||||
|
||||
total: 24000 comparisons (any disagreement would have failed the build)
|
||||
@@ -0,0 +1,24 @@
|
||||
Operation counts, brute force vs window / two pointers (counted, not timed)
|
||||
===========================================================================
|
||||
|
||||
Max sum of k=100 consecutive elements: element reads
|
||||
n brute force sliding window ratio
|
||||
1000 90,100 1,900 47.4x
|
||||
2000 190,100 3,900 48.7x
|
||||
4000 390,100 7,900 49.4x
|
||||
8000 790,100 15,900 49.7x
|
||||
|
||||
Pair search, target absent (worst case) in a sorted array 0..n-1: checks / steps
|
||||
n all pairs two pointers
|
||||
1000 499,500 999
|
||||
2000 1,999,000 1,999
|
||||
4000 7,998,000 3,999
|
||||
8000 31,996,000 7,999
|
||||
|
||||
minWindow on random strings over A-D, t="ABCD" (seed 42): pointer moves
|
||||
The loop is nested but each pointer only moves forward, so total moves stay linear.
|
||||
n right moves left moves valid windows
|
||||
1000 1,000 996 996
|
||||
2000 2,000 1,996 1,996
|
||||
4000 4,000 3,996 3,996
|
||||
8000 8,000 7,993 7,993
|
||||
@@ -0,0 +1,18 @@
|
||||
Four classic mistakes, each reproduced
|
||||
======================================
|
||||
|
||||
1. longest substring without repeats, left = lastSeen + 1 WITHOUT Math.max
|
||||
input "abba": buggy = 3 correct = 2
|
||||
at the final 'a', lastSeen('a') = 0, so the buggy code moves left from 2 back to 1
|
||||
|
||||
2. minimum-size subarray window used on input that contains negatives
|
||||
target 3, input [-2, -2, 3]: window = 0 ("none") brute force = 1 ([3])
|
||||
the running sum is -1 when the 3 arrives, so the window never looks valid
|
||||
|
||||
3. 3Sum without skipping duplicates
|
||||
input [-1, 0, 1, 2, -1, -4]
|
||||
buggy = [[-1, -1, 2], [-1, 0, 1], [-1, 0, 1]]
|
||||
correct = [[-1, -1, 2], [-1, 0, 1]]
|
||||
|
||||
4. two pointers on an array that is NOT sorted
|
||||
input [3, 2, 4], target 6: twoSumSorted = [] but 2 + 4 = 6 exists (brute force: true)
|
||||
Reference in New Issue
Block a user