Writing Interview Code
How you write code matters as much as whether it works. Here's how to write interview-quality code.
Code Quality Principles
1. Clarity Over Cleverness
❌ Bad:
def f(a,t):
d={}
for i,n in enumerate(a):
if t-n in d:return [d[t-n],i]
d[n]=i
✅ Good:
def two_sum(nums, target):
"""Find indices of two numbers that sum to target."""
seen = {}
for index, num in enumerate(nums):
complement = target - num
if complement in seen:
return [seen[complement], index]
seen[num] = index
return [] # No solution found
Why better:
- Descriptive names
- Clear logic flow
- Comments where helpful
- Handles no-solution case
2. Meaningful Names
Good Variable Names:
# ✓ Descriptive
left, right = 0, len(nums) - 1
max_profit = 0
char_frequency = {}
# ✗ Cryptic
l, r = 0, len(n) - 1
mp = 0
cf = {}
Good Function Names:
# ✓ Clear intent
def find_max_profit(prices):
def is_valid_palindrome(s):
def calculate_sum(numbers):
# ✗ Unclear
def process(arr):
def check(s):
def calc(nums):
3. Handle Edge Cases
def find_max(nums):
# Handle edge cases first
if not nums:
return None
if len(nums) == 1:
return nums[0]
# Main logic
max_val = nums[0]
for num in nums[1:]:
max_val = max(max_val, num)
return max_val
4. Use Proper Data Structures
❌ Poor choice:
# Using list for membership testing
def has_duplicate(nums):
seen = []
for num in nums:
if num in seen: # O(n) lookup!
return True
seen.append(num)
return False
✅ Good choice:
# Using set for O(1) lookup
def has_duplicate(nums):
seen = set()
for num in nums:
if num in seen: # O(1) lookup!
return True
seen.add(num)
return False
Code Organization
Start with Function Signature
def longest_substring(s: str, k: int) -> int:
"""
Find longest substring with at most k distinct characters.
Args:
s: Input string
k: Maximum distinct characters allowed
Returns:
Length of longest valid substring
"""
# Your code here
Use Helper Functions
def solve_complex_problem(data):
# Main function stays clean
if not is_valid_input(data):
return None
processed = preprocess(data)
result = find_solution(processed)
return postprocess(result)
def is_valid_input(data):
"""Validate input data."""
return data and len(data) > 0
def preprocess(data):
"""Prepare data for processing."""
return sorted(data)
def find_solution(data):
"""Core algorithm logic."""
# Implementation here
pass
def postprocess(result):
"""Format result."""
return result
Organize Logic Clearly
def binary_search(nums, target):
# 1. Initialize
left, right = 0, len(nums) - 1
# 2. Search
while left <= right:
mid = left + (right - left) // 2
# 3. Check and update
if nums[mid] == target:
return mid
elif nums[mid] < target:
left = mid + 1
else:
right = mid - 1
# 4. Not found
return -1
Common Patterns Done Right
Pattern 1: Two Pointers
def two_pointer_template(arr):
left, right = 0, len(arr) - 1
while left < right:
# Process current position
if condition(arr[left], arr[right]):
# Found answer or update result
return result
elif arr[left] < arr[right]:
left += 1
else:
right -= 1
return default_result
Pattern 2: Sliding Window
def sliding_window_template(arr, k):
window_state = {}
left = 0
result = 0
for right in range(len(arr)):
# Expand window
add_to_window(window_state, arr[right])
# Shrink if needed
while not is_valid(window_state, k):
remove_from_window(window_state, arr[left])
left += 1
# Update result
result = max(result, right - left + 1)
return result
Pattern 3: DFS/Backtracking
def backtrack_template(nums):
result = []
current = []
def dfs(index):
# Base case
if index == len(nums):
result.append(current[:]) # Make a copy!
return
# Include current element
current.append(nums[index])
dfs(index + 1)
current.pop()
# Exclude current element
dfs(index + 1)
dfs(0)
return result
Interview-Specific Tips
Tip 1: Code as You Explain
# BAD: Silent coding
*types code silently*
# GOOD: Narrate your code
"I'll create a hash map to store numbers we've seen..."
seen = {}
"Now I'll iterate through the array..."
for index, num in enumerate(nums):
"For each number, I calculate its complement..."
complement = target - num
Tip 2: Leave Space for Edge Cases
def solve(arr, k):
# TODO: handle edge cases
# Main logic here
result = process(arr, k)
return result
Then come back and add:
def solve(arr, k):
# Handle edge cases
if not arr or k <= 0:
return []
if k > len(arr):
return arr
# Main logic here
result = process(arr, k)
return result
Tip 3: Use Standard Library Wisely
# Collections
from collections import defaultdict, Counter, deque
# Show you know the tools
freq = Counter(nums) # Better than manual dict
queue = deque() # Better than list for queue
graph = defaultdict(list) # Clean graph representation
# Heapq for priority queues
import heapq
heap = []
heapq.heappush(heap, item)
heapq.heappop(heap)
Tip 4: Consistent Style
Pick a style and stick with it:
# Consistent naming
def camel_case_names():
my_variable = 10
another_variable = 20
# Consistent spacing
if condition:
do_something()
# Consistent operators
result = a + b
result = c * d
Code Review Checklist
Before saying "I'm done":
- Variable names are clear
- No magic numbers (use constants)
- Edge cases handled
- Appropriate data structures
- Time/space complexity as expected
- No obvious bugs
- Code is readable
Common Mistakes
❌ Off-by-One Errors
# Wrong
for i in range(len(arr) - 1): # Misses last element!
# Right
for i in range(len(arr)):
❌ Modifying While Iterating
# Dangerous
for item in my_list:
my_list.remove(item)
# Safe
my_list = [item for item in my_list if condition(item)]
❌ Integer Division Issues
# Python 2 style (wrong in Python 3)
mid = (left + right) / 2 # Returns float!
# Correct
mid = (left + right) // 2
# Or safer (avoids overflow in other languages)
mid = left + (right - left) // 2
❌ Forgetting Return Values
# Wrong
def process(arr):
result = []
# ... do work ...
# Forgot to return!
# Right
def process(arr):
result = []
# ... do work ...
return result
Key Takeaway
Write code as if you're pair programming with someone you respect. Clear, correct, and well-organized code demonstrates professionalism and makes you someone others want to work with.