Skip to content
DSA Grind
All 26 sections

Coding Interview Tips & Strategies

NoteUpdated
On this page

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
  • 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)

  1. Repeat the question back to the interviewer
  2. 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.)
  3. State your assumptions clearly

Phase 2: Design the Approach (5-10 min)

  1. Start with brute force — explain it, state its complexity, explain why it’s slow
  2. Interviewer will ask: “Can we do better?”
  3. Look for repeated work — can you cache/memoize results?
  4. Consider which data structures could help
  5. Enumerate data structures as a last resort: HashMap? Heap? Stack? Trie?
  6. 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)

  1. Review your code as if seeing it for the first time
  2. Step through with small test cases — trace the code, not the algorithm
  3. Write tests before being asked — huge bonus points
  4. Emulate a debugger: jot down variable values at each step
  5. Look for short-circuit evaluation opportunities
  6. Refactor duplicated code
  7. State time and space complexity — annotate code sections with their costs
  8. 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

  1. Pick your programming language
  2. Review CS fundamentals
  3. Practice 100-200 problems (pattern-based)
  4. Internalize the do’s and don’ts
  5. Mock interview with peers or platforms
  6. Interview with confidence