Coding Interview Tips & Strategies
NoteUpdated
On this page
- 1. Picking a Programming Language
- 2. Preparation Strategy
- Mastery Through Practice
- How to Study (Don’t Memorize!)
- Recommended Resources
- 3. Phases of a Coding Interview
- Phase 1: Understand the Problem (3-5 min)
- Phase 2: Design the Approach (5-10 min)
- Phase 3: Write the Code (15-25 min)
- Phase 4: Review and Test (5-10 min)
- 4. Topic-Specific Tips & Tricks
- General Tips
- Arrays / Sequences
- Strings
- Trees
- Graphs
- Linked Lists
- Dynamic Programming
- Intervals
- Binary / Bit Manipulation
- Math
- Heaps
- Matrix
- 5. After the Interview
- 6. The Success Formula
Extracted from How to Rock the Coding Interview by Yangshun Tay (Google, Airbnb, Dropbox offers) and the Blind 75 series by Uluc Ozdenvar.
1. Picking a Programming Language
- Choose a language you are extremely familiar with over one the company uses
- Best choices: Python (most concise), Java (strong typing, rich stdlib), C++
- Avoid: Low-level languages like C or Go (lack built-in data structures)
- For domain-specific roles (frontend, iOS, Android), use the relevant language
- If your language lacks a data structure (e.g., no built-in heap in JS), ask the interviewer if you can assume it exists with known time complexities
2. Preparation Strategy
Mastery Through Practice
- Solve 100-200 LeetCode questions for solid coverage
- LeetCode questions are most similar to real interview questions (vs. HackerRank/CodeForces which are more competitive-programming style)
- Learn time/space complexities of common operations in your language
- Know the underlying sorting algorithm (
Arrays.sort()in Java uses Dual-Pivot Quicksort for primitives, TimSort for objects) - Add complexity analysis as comments after solving — practice verbalizing analysis
How to Study (Don’t Memorize!)
- DO NOT memorize solutions — understand the techniques and patterns
- People have already solved these problems to perfection; learn from their solutions
- Once you understand patterns, you’ll see them emerge across problems
- The goal is pattern recognition, not recall
Recommended Resources
- AlgoMonster — Data-driven, teaches key patterns (one-time payment)
- Grokking the Coding Interview — Pattern-based approach with multi-language solutions
- Cracking the Coding Interview — Classic reference book
- LeetCode — Primary practice platform
- interviewing.io — Free anonymous mock interviews with Google/Meta engineers
- Pramp — Peer-to-peer mock interview platform
3. Phases of a Coding Interview
Phase 1: Understand the Problem (3-5 min)
- Repeat the question back to the interviewer
- Ask clarifying questions — even if you think it’s clear:
- How big is the input size?
- What’s the range of values?
- Are there negative numbers? Floating points? Empty inputs?
- Are there duplicates?
- What are extreme cases?
- How is the input stored? (list vs. trie, etc.)
- State your assumptions clearly
Phase 2: Design the Approach (5-10 min)
- Start with brute force — explain it, state its complexity, explain why it’s slow
- Interviewer will ask: “Can we do better?”
- Look for repeated work — can you cache/memoize results?
- Consider which data structures could help
- Enumerate data structures as a last resort: HashMap? Heap? Stack? Trie?
- Agree on the approach with your interviewer BEFORE coding
Phase 3: Write the Code (15-25 min)
- Use clear variable names (not single letters unless for iteration)
- On whiteboard: use shorter variable names to save writing time
- Explain what you’re writing as you code (high-level, not line-by-line reading)
- Avoid copy-pasting large code blocks — extract into helper functions instead
- If copying a line, change variables where needed (copy-paste bugs are common!)
Phase 4: Review and Test (5-10 min)
- Review your code as if seeing it for the first time
- Step through with small test cases — trace the code, not the algorithm
- Write tests before being asked — huge bonus points
- Emulate a debugger: jot down variable values at each step
- Look for short-circuit evaluation opportunities
- Refactor duplicated code
- State time and space complexity — annotate code sections with their costs
- Explain trade-offs vs. alternative approaches
4. Topic-Specific Tips & Tricks
General Tips
- Always validate input first (invalid, empty, negative, different types)
- Check for off-by-one errors
- Use a mix of functional and imperative programming
- Write pure functions (easier to reason about, fewer bugs)
- Avoid mutating function parameters (especially pass-by-reference)
- Don’t mutate global variables
- Classic trade-off: more memory = faster runtime
- HashMaps are your best friend — when stuck, try a HashMap first
Arrays / Sequences
- Sorted or partially sorted? → Binary search
- Can you sort it first? (Check if order matters before sorting)
- Summation/multiplication of subarrays? → Prefix/suffix sums or products
- O(1) space with values 1-N? → Use the array itself as a hash table (negate values)
- Slicing/concatenating is O(n) — use start/end indices instead
- Try traversing from the right side
- Sliding window for substring/subarray problems
- Two sequences? → One index per sequence
- Corner cases: empty, 1-2 elements, all duplicates
Strings
- Ask about character set and case sensitivity
- Anagram comparison → HashMap counter (or
int[26]for lowercase) - Counter space is O(1), not O(n) (bounded by alphabet size = 26)
- Look up: Trie/Prefix Tree, Rabin-Karp (rolling hash), KMP (substring search)
- Non-repeating characters? → 26-bit bitmask
- Anagram detection: sort both (O(n log n)), prime mapping (O(n)), or frequency count (O(n))
- Palindrome: reverse and compare, or two pointers from both ends
- Counting palindromes: expand outward from middle (check both even and odd length)
- Corner cases: empty, single char, single distinct char
Trees
- Recursion is the default approach for trees
- Base case: node is
null - Level-by-level traversal? → BFS (queue)
- Recursive function may need to return two values
- If summation along path: check for negative nodes
- Know pre-order, in-order, post-order (both recursive AND iterative)
- BST in-order gives sorted order
- Validate BST: in-order should be strictly increasing
- BST solutions usually run faster than O(n)
- Corner cases: empty, single node, two nodes, skewed (like a linked list)
Graphs
- Know representations: adjacency matrix, adjacency list, HashMap of HashMaps
- Some “trees” are actually graphs — clarify, then handle cycles with a visited set
- Know: BFS, DFS, Topological Sort, Dijkstra’s
- Rare but possible: Bellman-Ford, Floyd-Warshall, Prim’s, Kruskal’s
- 2D matrices are graphs — cells are nodes, adjacent cells are edges
- DFS on matrix template: check boundary, mark visited, explore 4 directions
- Corner cases: empty, 1-2 nodes, disjoint, cycles
Linked Lists
- Insertion/deletion is O(1) (unlike arrays which need shifting)
- Dummy node at head/tail eliminates edge cases
- Can sometimes solve without extra storage (borrow from reverse-list technique)
- Deletion: modify values or change pointers (may need previous reference)
- Partitioning: create two separate lists, join them back
- Think: “How would I solve this on an array?” then adapt
- Two pointer tricks:
- Kth from end: one pointer k ahead, when it reaches end, the other is at target
- Cycle detection: fast (2x speed) and slow — if they meet, cycle exists
- Middle node: fast (2x) and slow — when fast reaches end, slow is at middle
- Know these routines: count nodes, reverse, find middle, merge two lists
- Corner cases: single node, two nodes, has cycle (clarify with interviewer)
Dynamic Programming
- Used for optimization problems (min, max, count)
- Only way to get better: practice (recognition comes with experience)
- Space optimization: often only need last 2 values or last 2 rows
Intervals
- Always sort by start value first
- Know how to check overlap:
a.start < b.end && b.start < a.end - Know how to merge:
[min(a.start, b.start), max(a.end, b.end)] - Clarify: are
[1,2]and[2,3]overlapping? (affects equality checks) - Corner cases: single interval, non-overlapping, one consumed by another, duplicates
Binary / Bit Manipulation
- Test kth bit:
num & (1 << k) != 0 - Set kth bit:
num |= (1 << k) - Clear kth bit:
num &= ~(1 << k) - Toggle kth bit:
num ^= (1 << k) - Power of 2 check:
num & (num - 1) == 0 - Corner cases: overflow/underflow, negative numbers
Math
- Division/modulo → check for division by 0
- “Multiple of a number” → modulo
- Check for overflow/underflow in typed languages (Java, C++)
- Consider negative numbers and floating points
- Faster than O(n) for power/sqrt/division → binary search
- Formulas: Sum(1..N) = n(n+1)/2, GP sum = 2^(n+1)-1, nPr, nCr
Heaps
- See “top K” or “lowest K” → Heap
- Top K elements: use Min Heap of size K (iterate, push, evict min when size > K)
Matrix
- Usually involves DP or graph traversal
- Make a copy for visited state or DP table
- Games (Tic-Tac-Toe, Sudoku): verify horizontally, then transpose and reuse
- Corner cases: empty, 1x1, single row/column
5. After the Interview
- If asked about scale (input too large for memory, streaming data):
- Answer: divide and conquer — distributed processing, read chunks, process, combine
- This is a common Google follow-up
6. The Success Formula
- Pick your programming language
- Review CS fundamentals
- Practice 100-200 problems (pattern-based)
- Internalize the do’s and don’ts
- Mock interview with peers or platforms
- Interview with confidence