Python Interview Patterns
📖 Concept
Mastering Python interview patterns is about recognizing recurring problem structures and applying the right algorithmic technique efficiently. Interviewers evaluate not just correctness but your ability to communicate, analyze complexity, and leverage Python-specific features.
Core coding patterns every Python developer should know:
| Pattern | When to Use | Python Advantage |
|---|---|---|
| Two Pointers | Sorted arrays, palindrome checks | Slicing syntax, reversed() |
| Sliding Window | Subarray/substring problems | collections.deque, slicing |
| Hash Map Counting | Frequency, anagram, two-sum | collections.Counter, defaultdict |
| Stack/Queue | Parentheses matching, BFS/DFS | list as stack, deque as queue |
| Binary Search | Sorted data, search space reduction | bisect module |
| Dynamic Programming | Overlapping subproblems, optimal substructure | functools.lru_cache for top-down memoization |
| Backtracking | Permutations, combinations, constraint satisfaction | Generators with yield |
| Graph Traversal | Connected components, shortest paths | defaultdict(list) adjacency lists |
Whiteboard and live-coding strategies:
- Clarify first — restate the problem, ask about edge cases, confirm input/output types
- Brute force then optimize — always start with a working O(n^2) solution before jumping to O(n)
- Talk through your thought process — interviewers want to see how you reason, not just the final code
- Test with examples — walk through your code with the given example and an edge case
Python-specific tricks that impress interviewers:
- Use
enumerate()instead of manual index tracking - Leverage
zip()for parallel iteration - Apply
collections.Counterfor frequency problems instead of manual dictionaries - Use
itertoolsfor combinatorial problems (permutations,combinations,product) - Apply
functools.lru_cacheto convert recursive solutions into memoized DP with one decorator - Use tuple unpacking and multiple assignment for clean swaps:
a, b = b, a
Time and space complexity analysis is mandatory. Always state the Big-O for both before and after optimization. Be prepared to justify why your approach is optimal or discuss trade-offs between time and space.
💻 Code Example
1# ============================================================2# Python Interview Patterns — Common Solutions3# ============================================================4from collections import Counter, defaultdict, deque5from functools import lru_cache6import bisect789# --- Pattern 1: Two Pointers ---10def two_sum_sorted(nums, target):11 """Find two numbers in a SORTED array that sum to target. O(n) time."""12 left, right = 0, len(nums) - 113 while left < right:14 current_sum = nums[left] + nums[right]15 if current_sum == target:16 return [left, right]17 elif current_sum < target:18 left += 119 else:20 right -= 121 return []222324def is_palindrome(s):25 """Check if string is a palindrome (ignoring non-alphanumeric). O(n)."""26 cleaned = [c.lower() for c in s if c.isalnum()]27 return cleaned == cleaned[::-1]282930# --- Pattern 2: Sliding Window ---31def max_sum_subarray(nums, k):32 """Maximum sum of any contiguous subarray of size k. O(n)."""33 if len(nums) < k:34 return 035 window_sum = sum(nums[:k])36 max_sum = window_sum37 for i in range(k, len(nums)):38 window_sum += nums[i] - nums[i - k] # slide the window39 max_sum = max(max_sum, window_sum)40 return max_sum414243def longest_unique_substring(s):44 """Length of longest substring without repeating chars. O(n)."""45 char_index = {}46 max_len = 047 start = 048 for end, char in enumerate(s):49 if char in char_index and char_index[char] >= start:50 start = char_index[char] + 151 char_index[char] = end52 max_len = max(max_len, end - start + 1)53 return max_len545556# --- Pattern 3: Hash Map / Counter ---57def group_anagrams(strs):58 """Group anagrams together using sorted-key hashing. O(n * k log k)."""59 groups = defaultdict(list)60 for word in strs:61 key = tuple(sorted(word))62 groups[key].append(word)63 return list(groups.values())646566def top_k_frequent(nums, k):67 """Return k most frequent elements. O(n) with bucket sort."""68 count = Counter(nums)69 # Bucket sort: index = frequency, value = list of nums with that freq70 buckets = [[] for _ in range(len(nums) + 1)]71 for num, freq in count.items():72 buckets[freq].append(num)73 result = []74 for freq in range(len(buckets) - 1, 0, -1):75 for num in buckets[freq]:76 result.append(num)77 if len(result) == k:78 return result79 return result808182# --- Pattern 4: Stack ---83def valid_parentheses(s):84 """Check if parentheses are balanced. O(n) time, O(n) space."""85 stack = []86 pairs = {")": "(", "}": "{", "]": "["}87 for char in s:88 if char in "({[":89 stack.append(char)90 elif char in pairs:91 if not stack or stack[-1] != pairs[char]:92 return False93 stack.pop()94 return len(stack) == 0959697# --- Pattern 5: Dynamic Programming with lru_cache ---98@lru_cache(maxsize=None)99def climb_stairs(n):100 """Number of ways to climb n stairs (1 or 2 steps). O(n) with memo."""101 if n <= 2:102 return n103 return climb_stairs(n - 1) + climb_stairs(n - 2)104105106@lru_cache(maxsize=None)107def longest_common_subsequence(text1, text2, i=0, j=0):108 """LCS length using top-down DP with memoization."""109 if i >= len(text1) or j >= len(text2):110 return 0111 if text1[i] == text2[j]:112 return 1 + longest_common_subsequence(text1, text2, i + 1, j + 1)113 return max(114 longest_common_subsequence(text1, text2, i + 1, j),115 longest_common_subsequence(text1, text2, i, j + 1),116 )117118119# --- Pattern 6: BFS / Graph Traversal ---120def num_islands(grid):121 """Count islands in a 2D grid using BFS. O(m*n)."""122 if not grid:123 return 0124 rows, cols = len(grid), len(grid[0])125 visited = set()126 islands = 0127128 def bfs(r, c):129 queue = deque([(r, c)])130 visited.add((r, c))131 while queue:132 row, col = queue.popleft()133 for dr, dc in [(0, 1), (0, -1), (1, 0), (-1, 0)]:134 nr, nc = row + dr, col + dc135 if (0 <= nr < rows and 0 <= nc < cols136 and (nr, nc) not in visited137 and grid[nr][nc] == "1"):138 visited.add((nr, nc))139 queue.append((nr, nc))140141 for r in range(rows):142 for c in range(cols):143 if grid[r][c] == "1" and (r, c) not in visited:144 bfs(r, c)145 islands += 1146 return islands147148149# --- Pattern 7: Binary Search ---150def search_insert_position(nums, target):151 """Find insert position for target in sorted array. O(log n)."""152 return bisect.bisect_left(nums, target)153154155def find_first_and_last(nums, target):156 """Find first and last index of target in sorted array. O(log n)."""157 left = bisect.bisect_left(nums, target)158 right = bisect.bisect_right(nums, target) - 1159 if left <= right and left < len(nums) and nums[left] == target:160 return [left, right]161 return [-1, -1]162163164# --- Quick demo ---165if __name__ == "__main__":166 print(two_sum_sorted([1, 3, 5, 7, 11], 12)) # [1, 4]167 print(group_anagrams(["eat", "tea", "tan", "ate", "nat", "bat"]))168 print(top_k_frequent([1, 1, 1, 2, 2, 3], 2)) # [1, 2]169 print(valid_parentheses("({[]})")) # True170 print(climb_stairs(10)) # 89171 print(longest_unique_substring("abcabcbb")) # 3
🏋️ Practice Exercise
Exercises:
Implement a
three_sum(nums, target)function that finds all unique triplets summing to target. Use the two-pointer pattern after sorting. Ensure no duplicate triplets in the output. Analyze time complexity.Solve the "minimum window substring" problem using the sliding window pattern: given strings
sandt, find the smallest window insthat contains all characters oft. UseCounterfor character tracking.Build a
LRU Cacheclass usingcollections.OrderedDictthat supportsget(key)andput(key, value)in O(1) time. Write at least 6 test cases covering eviction, updates, and edge cases.Solve "course schedule" (topological sort): given
ncourses and prerequisite pairs, determine if all courses can be finished. Implement both DFS (cycle detection) and BFS (Kahn's algorithm) solutions. Compare their approaches.Implement a bottom-up DP solution for the "coin change" problem: given denominations and an amount, find the minimum number of coins. Then convert it to a top-down solution using
@lru_cache. Compare both approaches.Create a timed coding challenge script: pick 3 problems from the patterns above, set a 45-minute timer, solve them, then review your solutions for correctness, edge cases, and complexity. Record your solve times and track improvement over sessions.
⚠️ Common Mistakes
Jumping into coding without clarifying the problem first. Always ask about input constraints, edge cases (empty input, single element, negative numbers), and expected output format before writing a single line.
Ignoring Python's standard library — writing manual frequency counters instead of using
collections.Counter, implementing binary search from scratch instead of usingbisect, or building permutations manually instead of usingitertools.permutations.Forgetting to analyze and communicate time/space complexity. Interviewers expect you to state Big-O before and after optimization. Saying 'it runs fast' is not an answer — say 'O(n log n) time, O(n) space' explicitly.
Using
list.index()orinon lists inside loops, creating hidden O(n^2) complexity. Convert to asetordictfor O(1) lookups when checking membership repeatedly.Not testing edge cases: empty arrays, single-element inputs, all duplicates, already sorted data, and maximum constraints. Many interview failures come from off-by-one errors or unhandled boundary conditions.
💼 Interview Questions
🎤 Mock Interview
Practice a live interview for Python Interview Patterns