Video summary
ТЫ БУДЕШЬ СРАДАТЬ ОТ АЛГОРИТМОВ! (пока не посмотришь это видео)
Main summary
Key takeaways
Main ideas / lessons
- Preparation philosophy: Don’t rely on memorizing solutions to individual problems. Instead, learn reusable algorithmic patterns/frameworks and recognize “green flags” (task cues) that indicate which pattern applies.
- Video structure (overall):
- Start from a popular LeetCode topic
- Look at interview/statistics emphasis (frequency “green/yellow/red” zones)
- Teach the core patterns within the topic
- Give example tasks and show how to solve them
- Combine knowledge into a single framework for choosing the right pattern quickly
- Core meta-skill: When you see the problem wording, quickly identify which pattern is relevant (often via task structure like “two pointers”, “fixed window”, “frequency counting”, etc.).
Detailed methodology / instructions by topic
1) Two Pointers (indexing/sides; “fast & slow”)
Pattern A: Two pointers on a sorted array (“two sides”)
Task cues: Sorted array; often “two numbers add up to target.”
Method
- Initialize:
L = start(beginning)R = end(last index)
- Loop while
L < R:- Compute
sum = nums[L] + nums[R] - If
sum < target: moveLright - If
sum > target: moveRleft - If
sum == target: return positions / answer
- Compute
- If no match: return
-1(or equivalent)
Complexities: Time O(n), memory O(1).
Pattern B: Two pointers for palindrome check
Task cues: “Given a word, check if palindrome.”
Method
Lat left end,Rat right end- While
L < R: compare characters; move inward accordingly - If all pairs match → palindrome else not
Core idea: Shrink the window between pointers.
Pattern C: Two pointers for common elements of two sorted arrays (“two arrays, one pointer each”)
Task cues: “Find common elements between two sorted arrays.”
Method
- Initialize pointers
P1,P2at starts - While both are within bounds:
- If
arr1[P1] < arr2[P2]: incrementP1 - If
arr1[P1] > arr2[P2]: incrementP2 - If equal:
- Add to result
- Increment both
- If
Complexities: Time O(n + m), memory proportional to output.
Pattern D: Fast & Slow pointers (in-place zero/space operations)
Task cues: Modify array/string in-place while maintaining order.
Method
- Initialize:
fastreads through arrayslowwrites next “kept” position
- Loop while
fastin bounds:- If element is “allowed” (e.g., non-zero): swap or write to
slow, then advance both - If element is “discarded” (e.g., zero): advance only
fast
- If element is “allowed” (e.g., non-zero): swap or write to
- End: non-discarded elements end up at the front; discards at end.
Example cue logic:
slow= write indexfast= read index
Complexities: Time O(n), memory O(1).
Final framework for two pointers
- If two arrays: use “each-pointer” pattern.
- If in-place modification: use “fast & slow.”
- Else, prefer “two sides” for sorted/symmetric narrowing.
2) Sliding Window
Pattern A: Fixed-size sliding window
Task cues: “Max/min of k consecutive elements/products/properties.”
Method
- Compute sum/product for first window of size
k - Slide:
- Subtract left element leaving window
- Add right element entering window
- Track max (or min)
Transition formula: new = old - left + right
Complexities: Time O(n), memory O(1).
Pattern B: Non-overlapping windows
Task cues: Arrays where segments/ranges are built greedily and do not overlap (often “combine consecutive runs”).
Method
- Initialize
LandR - Expand
Rwhile condition holds (e.g., strictly increasing by 1) - Process the found run into answer
- Move both to next starting point
Complexities: Time O(n), since pointers only advance.
Pattern C: Intersecting windows
Task cues: You can “keep extending” but must shrink to maintain a constraint (e.g., “max length with at most k flips”).
Method
- Initialize:
L = 0,R = -1- Track constraint counter (e.g., zeros in window)
- Expand
Runtil constraint would be violated - Update answer based on valid window
- Narrow by moving
Land updating counter - Repeat until
Lexits array
Key rule: Maintain window validity by updating the constraint state during both expansion and contraction.
Complexities: Time O(n), memory O(1).
Sliding Window identification rules
- “Fixed length k” → fixed window.
- “Groups don’t intersect” → non-overlapping.
- “Need to consider overlapping sequences under a constraint” → intersecting.
3) Hash Table Framework (frequency + key/value inversion)
Pattern A: Counting technique
Task cues: “Check possibility based on frequency” (palindrome anagram, anagram check, etc.)
Method
- Build dictionary:
count[char]++ - Post-process counts (e.g., palindrome condition: ≤1 odd frequency)
- Return based on rule
Complexities: Time O(n), memory O(#unique).
Pattern B: KVK (“key-value inversion” / frequency buckets)
Task cues: “Sort by frequency” or “top k frequent elements.”
Method
- Count frequencies:
count[elem] - Invert into buckets/array:
freqBuckets[freq].push(elem) - Traverse buckets from high frequency to low to build result
Complexities: Time roughly linear with bounded overhead; memory O(n).
Hash table decision rule
- If you need frequency comparisons/calculations → Counting.
- If you need ordering/sorting by frequency or extracting top-k → KVK.
4) Points & Segments (Intervals)
Pre-knowledge (basic definitions)
- Segment = pair coordinates.
- Intersection exists if:
max(start1, start2) <= min(end1, end2)
- Union of intersecting segments:
- start =
min(starts), end =max(ends) - (but only after verifying intersection)
- start =
Pattern A: Segment method (merge intersecting segments)
Method
- Sort segments by start
- Start result with first segment
- For each next segment:
- If it intersects the last result segment → merge
- Else → append as new segment
Complexity: Time O(n log n) due to sorting.
Pattern B: Two pointers on segments (intersections between two lists)
Method
- Put pointer
iat start of list A;jat start of list B - While both pointers are in range:
- If segments intersect → add intersection to result
- Move pointer with the smaller end forward
Complexities: Time O(n + m).
Pattern C: Dot method (events at points; max simultaneous rooms/platforms)
Task cues: “Max number of simultaneous active intervals.”
Method
- Transform each interval
[start, end]into points/events:(start, +1)(end, -1)
- Sort points by coordinate; for same coordinate, process
-1before+1(room becomes free before becomes busy) - Sweep with counter; answer = maximum counter value
Complexities: Time dominated by sorting O(n log n).
5) Binary Search
Pattern A: Basic binary search (boundary between good/bad)
Task cues: Sorted array; find last good (or first bad) boundary.
Method
- Define monotonic “good” predicate:
- If
nums[mid] <= target→ good else bad
- If
- Maintain
LandRsuch that:- after loop,
Llands on last good Ron first bad
- after loop,
- Final step: verify answer
Complexities: Time O(log n), memory O(1).
Pattern B: Double binary search (find first and last occurrence)
Task cues: Need range [first, last] for target.
Method
- Run binary search #1 to find boundary for last occurrence
- Run binary search #2 to find boundary for first occurrence
- If not found in either → return
[-1, -1]
Complexities: Time O(log n) overall (conceptually 2*log n).
Special case mentioned: rotated sorted array
- Use double binary search to find rotation offset, then binary search within shifted order.
Decision rule
- Simple boundary → basic.
- Need a range or require “preparation binary search” → double.
6) Stack (LIFO) and related variants
Pattern A: Stack of intermediate results
Task cues: Nested structure with validation (brackets matching, RPN evaluation).
Method
- Traverse elements:
- If opening → push
- If closing → pop and verify match
- At end: stack must be empty (for correctness)
Complexities: Time O(n), memory O(n).
Pattern B: Monotonic stack
Task cues: For each element, find nearest greater/smaller element to right/left.
Method (nearest greater to the right example)
- Traverse from right to left
- Maintain stack with monotonic property (e.g., decreasing/increasing depending on goal)
- While stack top violates condition, pop
- Answer for current is stack top (or
-1if empty) - Push current
Complexities: Time O(n) (each element pushed/popped at most once).
Pattern C: Pseudo-stack
Task cues: Brackets correctness where you only need balance magnitude, not actual stack contents.
Method
- Maintain
balance - On ‘(’ →
balance++ - On ‘)’ →
balance-- - If
balance < 0→ invalid immediately - End valid iff
balance == 0
Complexities: Time O(n), memory O(1).
Stack framework summary
- Nearest greater/smaller → monotonic stack.
- Need only stack size/balance → pseudo-stack.
- Otherwise nested/remembering types/values → intermediate stack.
7) Prefix Sum
Core idea
-
Prefix array allows O(1) range sum queries:
sum(i..j) = prefix[j] - prefix[i-1](with correct indexing). -
Useful for many aggregate queries on arrays/matrices.
Pattern A: Array sums (2D aggregation)
Task cues: Aggregate by rows/columns/diagonals in a 2D grid (rook/queen).
Method
- Precompute sums for each row and each column (and diagonals when needed)
- For each cell, compute attacked/affected sum using precomputed arrays
- Track max/min as required
Complexities: Typically O(n*m) time and O(n+m) memory.
Pattern B: Running prefix (replace suffix/prefix arrays with variables)
Task cues: Split point where left sum == right sum, etc.
Method
- Compute total sum
- Maintain
prefixsum variable while scanning - Compute
suffix = total - prefix - current - Check condition; update prefix as you move
Complexities: Time O(n), memory O(1).
8) Linked Lists
Pattern A: Dummy node (“dummy knot”)
Task cues: When deletion/insert at head would complicate cases; avoid special casing.
Method
- Create dummy node before head
- Use pointers to traverse and modify links
- Return
dummy.next(and delete dummy if no GC)
Complexity: Typically O(n) (depends on traversal).
Pattern B: Partial reversals
Task cues: Palindrome on singly linked list when you can’t traverse backward.
Method
- Find middle (slow/fast)
- Reverse only the second half
- Compare first half and reversed second half node-by-node
Complexities: Time O(n), memory O(1).
Also covered basics (not framed as “pattern”)
- Middle of singly list via slow/fast pointers.
- In-place reversal with pointer rewiring.
- Merging two sorted lists using dummy node.
Linked list decision rule
- If you need to build new list or deletion can touch head → dummy node.
- If you need two-sided comparison but list is singly → partial reversals.
9) Brute Force vs Backtracking (combinatorics)
Pattern A: Brute force
Task cues: Enumerate all possibilities with limited pruning (or none).
Method (phone keypad combinations example)
- Maintain a queue/deque of partial strings
- Pop first partial; if empty or partial length too short:
- Generate next letter options for next digit
- Append new partials to the queue
- Stop when partial length equals input length
- Collect all completed strings
Complexities: Exponential, e.g. O(4^n) in keypad case.
Pattern B: Backtracking
Task cues: Validity constraints can prune early (e.g., balanced parentheses).
Method (generate correct parentheses)
- Start with queue/deque holding:
- counts of open and close brackets used so far
- current partial string
- At each step:
- Add ‘(’ only if
openUsed < n - Add ‘)’ only if
closeUsed < openUsed
- Add ‘(’ only if
- Stop when length reaches
2n - Return all valid sequences
Key distinction: Prune invalid branches before reaching full length.
Complexity: Related to Catalan numbers (exponential but much smaller than full 2^(2n) enumeration).
Decision rule
- If you can prune invalid branches early → backtracking.
- If you effectively must try everything → brute force.
10) Trees (Binary trees emphasized): Bottom-up vs Top-down
Pattern A: Bottom-up
Meaning: Collect info from children to compute parent.
Method template
- Base case: empty node → return neutral value (e.g., 0 height)
- Recurse left/right
- Combine children results to form answer info
- Return value required by parent (often “height” even when answer uses “diameter”)
Example: Diameter of binary tree
- Update global maximum using
leftHeight + rightHeight - Return height up the recursion
Complexities: Time O(n), memory O(h) recursion depth.
Pattern B: Top-down
Meaning: Pass accumulated state from root to children.
Method template
- Base: empty node
- Recurse into children with updated parameter (sumSoFar, level, path constraints)
- Use recursion results to build answer (often boolean)
Example: Path sum root-to-leaf
- Pass
sumToHeredown - At leaf, compare to target
Complexities: Time O(n), memory O(h).
Tree framework rule
- Need “from leaves upward aggregation” → bottom-up.
- Need “carry information from root to children” → top-down.
11) Graphs: BFS/DFS + components + topological order
Graph basics
- Graph stored typically via adjacency list (hash map vertex → neighbor list).
- Connected component: maximal group of mutually reachable nodes (for undirected graphs).
Pattern A: BFS traversal (wave)
Task cues: Shortest path in unweighted graphs; distance in steps.
Method
- Initialize queue with start node; mark visited; store distance for start = 0
- While queue not empty:
- Pop front node
- For each neighbor:
- If not visited: mark visited, set neighbor distance = current + 1, push
- If finish found: return distance
- If never found: return -1
Complexities: Time O(n + m), memory O(n).
Pattern B: DFS traversal
Task cues: Reachability; exploring depth branches; cycle detection variants (not expanded here).
Method
- Use stack (LIFO) + visited
- Pop node, push unvisited valid neighbors
Complexities: Time O(n + m), memory O(n).
Rule of thumb
- “Minimum/shortest distance” → BFS.
- “In other cases” either can work, but BFS is practical for shortest paths.
Pattern C: Connected components
Method
- Build graph (adjacency list)
- Iterate over all vertices
- For each unvisited vertex: run BFS/DFS to mark its component; increment component count
Complexities: O(n + m).
Pattern D: Topological order / dependency order (Kahn’s algorithm)
Task cues: DAG ordering; “task prerequisites” ordering.
Method
- Compute indegree for each vertex
- Push all indegree==0 vertices into queue
- While queue not empty:
- Pop node; add to answer list
- For each outgoing edge to neighbor:
- decrement neighbor indegree
- if neighbor indegree becomes 0: push it
- If answer size == number of vertices → valid order; else → cycle exists → return empty list
Complexities: O(n + m).
Rule
- Need shortest path steps → shortest-path (BFS).