Interview Preparation
TL;DR
Technical interviews assess problem-solving under pressure. Success requires three elements: clear communication, efficient time management, and systematic testing. Clarify Phase (2 min): Restate problem in your own words, ask about edge cases, constraints, output format. Interviewer expects questions; silence suggests misunderstanding. Approach Phase (5-8 min): Outline approach verbally before coding. Discuss time/space trade-offs. Get feedback early; prevents wrong direction. Code Phase (15-20 min): Write clean code, not optimized code. Use variable names from problem statement. Declare data structures explicitly. Test as you write (mental trace through examples). Test Phase (5 min): Walk through code with provided examples. Catch off-by-one, null pointer, boundary issues. Common pitfalls (empty input, single element, duplicates). Optimize Phase (if time): Discuss possible optimizations. Implement if time allows. Communication throughout is as important as correctness.
Core Concepts
The UMPIRE Framework
Systematic interview approach ensuring no phase is skipped:
Understand: Restate problem. Ask clarifying questions. Confirm edge cases and constraints.
Match: Identify algorithmic pattern. "This looks like sliding window" or "This is tree traversal with memoization".
Plan: Outline approach pseudocode. Discuss complexity. Ask if approach is correct before coding.
Implement: Write code clearly. Handle edge cases. Use descriptive variable names from problem.
Review: Walk through code with examples. Verify logic. Check boundary conditions.
Evaluate: Discuss complexity. Suggest optimizations. Handle follow-up questions.
Time Management: 45-Minute Interview
Minutes 0-2: Clarify Requirements
- Restate problem in own words
- Ask about edge cases (empty, single, large, negative, duplicates)
- Confirm input/output format
- Identify constraints (sorted?, distinct?, range?)
Minutes 2-8: Outline Approach
- Identify pattern (sliding window, two-pointer, DFS, DP, greedy)
- Pseudocode (not implementation details)
- Estimate time/space complexity
- Discuss trade-offs with alternatives
Minutes 8-28: Implement
- Write clean, readable code
- Use variable names from problem
- Handle edge cases as you code
- Mentally trace through examples while writing
Minutes 28-38: Test & Debug
- Walk through provided example
- Test with edge cases (empty, single, boundary)
- Fix any bugs found
- Verify complexity assumptions
Minutes 38-45: Optimize/Discuss
- Can we improve time complexity?
- Can we reduce space complexity?
- How would this scale? Different inputs?
- Discuss alternative approaches
Communication Best Practices
Thinking Aloud: Continuously explain what you're doing. "I'll use a hash map to track frequencies" or "This is a boundary case where..." Silence is red flag.
Asking Questions: Clarify ambiguities. "Can the array be empty?" "Can there be duplicates?" "Is the array sorted?" Show engagement.
Explaining Trade-offs: "Sorted approach is O(n log n) but uses O(1) space. Hash table is O(n) average but O(n) space. I'll go with hash table for better time."
Accepting Feedback: If interviewer suggests different approach, don't defend yours. "That's a good point. Let me think about that approach" shows flexibility.
Admitting Uncertainty: "I'm not 100% sure about this edge case. Let me think through it" is better than confident wrong answer.
Common Pattern Recognition
Array/String Subproblem: Sliding window or two-pointer Sorted Array Search: Binary search Optimal Substructure: Dynamic programming Graph/Tree Traversal: DFS or BFS Frequency/Counting: Hash table Top K Elements: Heap Overlapping Intervals: Merge or sweep Constraint Satisfaction: Backtracking
Recognizing pattern immediately cuts design time.
Testing Strategy
Provided Example: Must pass. Good for understanding.
Edge Cases:
- Empty input
- Single element
- All same elements
- Boundary values (min/max)
- Duplicates
Medium Cases: Few elements (2-5). Verify logic works beyond trivial.
Special Structures: Sorted, reversed, alternating patterns. Can expose algorithm assumptions.
Walkthrough: Line by line with example in head. Catches logical errors before run.
Key Algorithms
Interview Complexity Analysis Checklist
| Aspect | What to Check |
|---|---|
| Time Complexity | Outer loops, nested iterations, recursive calls, operations per iteration |
| Space Complexity | Extra data structures, recursion depth, stack frames |
| Best Case | When input is optimally arranged (rare in interviews) |
| Worst Case | Adversarial input; what conditions trigger worst behavior |
| Average Case | Typical inputs; often same as worst but document assumptions |
Quick Complexity Estimation
- Count loops: n nested loops = O(n^k)
- Count recursive calls: multiply by branching factor
- Count operations per call: multiply overall
- Sum independent operations: add them
- Keep dominant term; drop constants
Practical Example
- Interview Walkthrough
- Python Interview Solution
- TypeScript Interview Solution
PROBLEM: "Find the maximum length of a subarray with sum >= target"
PHASE 1: CLARIFY (2 min)
Q: Can the array have negative numbers?
A: Yes, any integers
Q: Can the array be empty?
A: Assume at least one element
Q: Return length or the subarray itself?
A: Just the length
Q: Can there be no valid subarray?
A: Return 0
PHASE 2: APPROACH (6 min)
Pattern Recognition: "Subarray with property → sliding window"
Approach:
- Use two pointers: left, right
- Expand right to increase sum
- When sum >= target, try shrinking from left (maintain max length)
- Track maximum window size
Complexity: O(n) time, O(1) space
Alternatives:
- Brute force: try all subarrays = O(n²) [dismiss]
- Prefix sum + binary search = O(n log n) [slower]
- Sliding window = O(n) [best]
PHASE 3: CODE (15 min)
[Write clean code with edge case handling]
PHASE 4: TEST (10 min)
Example: arr = [1, 2, 3], target = 4
- [1]: sum=1, < 4
- [1,2]: sum=3, < 4
- [1,2,3]: sum=6, >= 4, length=3
- [2,3]: sum=5, >= 4, length=2
Maximum = 3 ✓
Edge: arr = [5], target = 4
- [5]: sum=5, >= 4, length=1 ✓
PHASE 5: OPTIMIZE (3 min)
Could we optimize further?
- Already O(n) time, O(1) space (optimal)
- Could parallelize if multiple machines (overkill)
- Current solution is optimal
PHASE 6: DISCUSS (5 min)
Follow-ups:
- What if we need the actual subarray, not just length?
Answer: Track start/end indices, return arr[start:end]
- How would this scale with 10^9 elements?
Answer: O(n) time, O(1) space scales perfectly; streaming model
- What if target could change per query?
Answer: Would need preprocessing; different problem
def max_subarray_length_ge_target(arr, target):
"""
Find maximum length of subarray with sum >= target.
Uses sliding window two-pointer approach.
Time: O(n), Space: O(1)
"""
# Edge case handling
if not arr:
return 0
left = 0
current_sum = 0
max_length = 0
# Expand window with right pointer
for right in range(len(arr)):
current_sum += arr[right]
# Shrink from left while sum >= target
while current_sum >= target and left <= right:
max_length = max(max_length, right - left + 1)
current_sum -= arr[left]
left += 1
return max_length
def test_solution():
"""Test with various cases"""
# Provided example
assert max_subarray_length_ge_target([1, 2, 3], 4) == 3
print("✓ Provided example passes")
# Edge cases
assert max_subarray_length_ge_target([5], 4) == 1
print("✓ Single element passes")
assert max_subarray_length_ge_target([1, 1, 1], 5) == 0
print("✓ No valid subarray passes")
# Negative numbers
assert max_subarray_length_ge_target([2, -1, 3], 3) == 2
print("✓ Negative numbers pass")
# All valid
assert max_subarray_length_ge_target([5, 5, 5], 10) == 3
print("✓ All valid passes")
print("\nAll tests passed!")
# Complexity Analysis (spoken aloud in interview)
"""
TIME COMPLEXITY: O(n)
- Outer loop: right pointer goes 0 to n once = O(n)
- Inner while: left pointer only moves forward once = O(n) total
- Combined: O(n) + O(n) = O(n)
SPACE COMPLEXITY: O(1)
- Only using left, right, current_sum, max_length variables
- No data structures that scale with input
- Constant space regardless of input size
BEST CASE: O(n) - must scan entire array
WORST CASE: O(n) - same as best case (consistent)
"""
test_solution()
function maxSubarrayLengthGeTarget(arr: number[], target: number): number {
/**
* Find maximum length of subarray with sum >= target.
* Sliding window approach.
*
* Time: O(n), Space: O(1)
*/
// Edge case
if (arr.length === 0) return 0;
let left = 0;
let currentSum = 0;
let maxLength = 0;
// Expand window with right pointer
for (let right = 0; right < arr.length; right++) {
currentSum += arr[right];
// Shrink from left while sum >= target
while (currentSum >= target && left <= right) {
maxLength = Math.max(maxLength, right - left + 1);
currentSum -= arr[left];
left++;
}
}
return maxLength;
}
// Test cases
function testSolution(): void {
// Provided example
console.assert(
maxSubarrayLengthGeTarget([1, 2, 3], 4) === 3,
"Provided example failed"
);
// Edge cases
console.assert(
maxSubarrayLengthGeTarget([5], 4) === 1,
"Single element failed"
);
console.assert(
maxSubarrayLengthGeTarget([1, 1, 1], 5) === 0,
"No valid subarray failed"
);
// Negative numbers
console.assert(
maxSubarrayLengthGeTarget([2, -1, 3], 3) === 2,
"Negative numbers failed"
);
console.log("All tests passed!");
}
// Complexity explained
const complexityAnalysis = `
TIME COMPLEXITY: O(n)
- Right pointer: 0 to n = O(n)
- Left pointer: only moves forward = O(n) amortized
- Total: O(n)
SPACE COMPLEXITY: O(1)
- Only scalar variables (left, currentSum, maxLength)
- No data structures proportional to input size
`;
testSolution();
Common Pitfalls
Jumping straight to code: Skipping clarification and approach planning. Results in solving wrong problem or inefficient solution. Always discuss approach first.
No communication: Thinking silently for 30 minutes. Interviewer can't assess reasoning. Think aloud constantly.
Ignoring edge cases: Assuming happy path only. Real interviews check empty, single, negative, boundary. Address explicitly.
Not testing your code: Writing solution and declaring done. Walk through with examples, catch bugs before interviewer does.
Dismissing alternative approaches: Defending chosen solution when interviewer suggests different approach. Show flexibility; consider suggestions seriously.
Pursuing perfection: Spending 20 minutes on perfect solution when "good enough" would pass. 80% solution working beats 100% solution incomplete.
Complexity analysis gaps: Hand-waving "it's O(n)". Explain specifically: which loops, what operations, how combined. Shows depth of understanding.
Self-Check
- If interviewer says "Let's move on" during coding, what does this likely mean? How should you respond?
- For a sliding window problem, what are the key variables to track and update?
- Walk through a complexity analysis for: "We loop from 1 to n, and for each iteration we call binary search on n elements". What's the complexity?
One Takeaway
Technical interviews are not memory tests or typing races. They assess communication, problem-solving approach, and code quality under pressure. Spend time upfront on clarification and approach design (10-15 minutes). Then implement cleanly, test thoroughly, and discuss trade-offs. The candidate who communicates clearly, asks good questions, and solves the problem systematically beats the candidate who codes faster but silently. Master the interview process, not just the algorithms.
References
- McDowell, G. L. (2015). Cracking the Coding Interview (6th ed.). CareerCup.
- Bhargava, A. Y. (2016). Grokking Algorithms. Manning Publications.