Lesson 9.1: Patterns & Heuristics
Patterns and heuristics are mental shortcuts and solution templates that allow programmers to quickly identify approaches for solving problems efficiently. They aren't exact formulas but guide intuition and accelerate development and debugging.
π Key Points
- Recognizing problem templates helps identify correct algorithms quickly.
- Sliding window and two pointers for sequence problems.
- Recursion with memoization for overlapping subproblems.
- Graph traversal for anything network/relationship-based.
- Greedy patterns for local optimization problems.
- Backtracking for generating combinations or permutations.
- Divide and conquer in sorting and search-based problems.
π§ͺ Examples
# Sliding window max sum example
arr = [1, 4, 2, 10, 23, 3, 1, 0, 20]
k = 4
window_sum = sum(arr[:k])
max_sum = window_sum
for i in range(len(arr) - k):
window_sum = window_sum - arr[i] + arr[i + k]
max_sum = max(max_sum, window_sum)
print(max_sum)
# Output: 39
Lesson 9.2: Tries & DSU
Tries (prefix trees) and DSU (Disjoint Set Union) are specialized structures used in many real-world systems like autocomplete engines, DNS servers, network grouping algorithms, and union-find operations.
π Key Points
- Tries store words in tree format β useful in dictionaries and search engines.
- DSU tracks connected components efficiently in networks.
- DSU uses path compression + union by rank for efficiency.
- Autocomplete features use Trie traversal for fast lookups.
- Tries optimize prefix-based queries like IP routing.
- DSU used in Kruskal's algorithm for MST.
- Both structures require careful space/time optimization.
π§ͺ Examples
# Trie insertion example
class TrieNode:
def __init__(self):
self.children = {}
self.end = False
def insert(root, word):
node = root
for ch in word:
if ch not in node.children:
node.children[ch] = TrieNode()
node = node.children[ch]
node.end = True
# DSU example
parent = list(range(5))
def find(x):
if parent[x] != x:
parent[x] = find(parent[x])
return parent[x]
def union(x, y):
root_x = find(x)
root_y = find(y)
if root_x != root_y:
parent[root_x] = root_y
Lesson 9.3: Interview Prep
Cracking coding interviews isnβt just about solving problems β it's about practicing core concepts repeatedly, analyzing patterns, and improving explanation skills. This lesson helps you prepare strategically for interviews.
π Key Points
- Practice common problems like 2-sum, LRU cache, binary trees.
- Master foundational topics: DSA, recursion, graphs.
- Use platforms like LeetCode, HackerRank, Codeforces.
- Follow the 5-step process: Understand β Plan β Code β Test β Optimize.
- Mock interviews help simulate real pressure and refine clarity.
- Review time/space complexity post-solution.
- Prepare for behavioral questions too.
π§ͺ Examples
# Two sum problem
nums = [2, 7, 11, 15]
target = 9
seen = {}
for i, num in enumerate(nums):
if target - num in seen:
print([seen[target - num], i])
seen[num] = i
# Output: [0, 1]