Startup to FAANG ยท Coding Rounds ยท India 2025

DSA โ€”
Zero to Interview
Ready

Every data structure and algorithm topic that appears in Indian tech interviews โ€” from basic arrays to dynamic programming. Covers every pattern asked at Amazon, Google, Flipkart, Swiggy, and 1-10 year experience rounds. With complexity analysis, templates, and problem patterns.

15 Modules
Big O to DP
Code Templates
Problem Patterns
Complexity Tables
Startup โ†’ FAANG
Module 01 ยท Foundations
โ— Beginner โ€” Must Know

Big O Notation & Complexity Analysis

Big O describes how an algorithm's time or space grows as input size (n) grows. Every single interview requires you to state the complexity of your solution. This is non-negotiable.

Growth Rate Comparison Visual
ComplexityNameExamplen=1000
O(1)ConstantArray index access, HashMap get/set1 op
O(log n)LogarithmicBinary search, balanced BST operations~10 ops
O(n)LinearArray scan, linked list traversal1,000 ops
O(n log n)LinearithmicMerge sort, heap sort, good sorting~10,000 ops
O(nยฒ)QuadraticBubble/insertion sort, nested loops1,000,000 ops
O(2โฟ)ExponentialRecursive Fibonacci, subset generation10ยณโฐยน ops โ€” avoid!
O(n!)FactorialPermutations, TSP brute forceastronomical โ€” never
Drop constants: O(3n) โ†’ O(n) | O(n/2) โ†’ O(n) Drop smaller terms: O(nยฒ + n) โ†’ O(nยฒ) | O(n + log n) โ†’ O(n) Nested loops MULTIPLY: two nested O(n) loops = O(nยฒ) Sequential operations ADD: O(n) + O(n) = O(n) (not O(2n))
01_complexity_examples.js
js
// O(1) โ€” constant, no matter size of input
const get = (arr, i) => arr[i];
const setMap = (map, k, v) => map.set(k, v);

// O(n) โ€” one pass through array
const sum = (arr) => arr.reduce((a, b) => a + b, 0);

// O(nยฒ) โ€” nested loops over same input
function hasDupe(arr) {
  for (let i = 0; i < arr.length; i++)         // n
    for (let j = i + 1; j < arr.length; j++)   // n-1, n-2...
      if (arr[i] === arr[j]) return true;        // โ†’ O(nยฒ)
  return false;
}
// Better: O(n) with HashSet
const hasDupeO1 = (arr) => arr.length !== new Set(arr).size;

// O(log n) โ€” halving the input each step
function binarySearch(arr, target) {
  let lo = 0, hi = arr.length - 1;
  while (lo <= hi) {
    const mid = lo + ((hi - lo) >> 1);     // avoid overflow
    if (arr[mid] === target) return mid;
    arr[mid] < target ? lo = mid + 1 : hi = mid - 1;
  }
  return -1;
}                                               // โ†’ O(log n) time, O(1) space

// Space complexity โ€” memory used
// O(1): variables only. O(n): array/map proportional to input.
// Recursive calls use O(depth) stack space!
Module 02 ยท Foundations
โ— Beginner

Arrays & Strings

Arrays are the most tested data structure. Almost every problem involves arrays. Master these operations, patterns, and built-in methods cold.

OperationArray TimeWhat happens
Access arr[i]O(1)Direct memory offset calculation
Search (unsorted)O(n)Must check every element
Search (sorted)O(log n)Binary search possible
Insert at endO(1) amortizedDynamic array may resize occasionally
Insert at start/midO(n)Must shift all elements right
Delete at endO(1)Just decrement length
Delete at start/midO(n)Must shift all elements left
02_arrays_patterns.js โ€” Most common patterns
js
// โ”€โ”€โ”€ Prefix Sum โ€” range query in O(1) after O(n) prep โ”€โ”€โ”€โ”€โ”€
function buildPrefix(arr) {
  const prefix = [0];
  for (const n of arr) prefix.push(prefix.at(-1) + n);
  return prefix;
}
// rangeSum(i, j) = prefix[j+1] - prefix[i]  โ†’ O(1) per query!

// โ”€โ”€โ”€ Kadane's Algorithm โ€” Maximum Subarray Sum O(n) โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function maxSubarray(nums) {
  let maxSum = -Infinity, curr = 0;
  for (const n of nums) {
    curr = Math.max(n, curr + n);      // extend or restart
    maxSum = Math.max(maxSum, curr);
  }
  return maxSum;
}

// โ”€โ”€โ”€ Dutch National Flag โ€” sort 0,1,2 in O(n) one pass โ”€โ”€โ”€โ”€
function sortColors(nums) {
  let lo = 0, mid = 0, hi = nums.length - 1;
  while (mid <= hi) {
    if (nums[mid] === 0) [nums[lo++], nums[mid++]] = [nums[mid], nums[lo]];
    else if (nums[mid] === 2) [nums[mid], nums[hi--]] = [nums[hi], nums[mid]];
    else mid++;
  }
}

// โ”€โ”€โ”€ String: Anagram check O(n) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function isAnagram(s, t) {
  if (s.length !== t.length) return false;
  const count = new Array(26).fill(0);
  for (let i = 0; i < s.length; i++) {
    count[s.charCodeAt(i) - 97]++;
    count[t.charCodeAt(i) - 97]--;
  }
  return count.every(c => c === 0);
}
Module 03 ยท Foundations
โ— Beginner โ†’ Mid

Linked Lists

Linked lists test pointer manipulation under pressure. The classic interview questions (reverse, detect cycle, find middle, merge sorted lists) follow predictable patterns. Learn the patterns, not the problems.

03_linked_list.js โ€” All classic patterns
js
class ListNode { constructor(val, next=null) { this.val=val; this.next=next; } }

// โ”€โ”€โ”€ Reverse Linked List O(n) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function reverse(head) {
  let prev = null, curr = head;
  while (curr) {
    const next = curr.next;  // save
    curr.next = prev;         // reverse pointer
    prev = curr;              // advance prev
    curr = next;              // advance curr
  }
  return prev;
}

// โ”€โ”€โ”€ Detect Cycle โ€” Floyd's Tortoise & Hare O(n) O(1) โ”€โ”€โ”€โ”€
function hasCycle(head) {
  let slow = head, fast = head;
  while (fast?.next) {
    slow = slow.next;          // 1 step
    fast = fast.next.next;     // 2 steps
    if (slow === fast) return true;   // they meet โ†’ cycle!
  }
  return false;
}

// โ”€โ”€โ”€ Find Middle โ€” slow/fast pointers โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function findMiddle(head) {
  let slow = head, fast = head;
  while (fast?.next) { slow = slow.next; fast = fast.next.next; }
  return slow;  // slow is at middle when fast reaches end
}

// โ”€โ”€โ”€ Merge Two Sorted Lists O(n+m) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function mergeSorted(l1, l2) {
  const dummy = new ListNode(0);  // dummy head trick
  let curr = dummy;
  while (l1 && l2) {
    if (l1.val <= l2.val) { curr.next = l1; l1 = l1.next; }
    else { curr.next = l2; l2 = l2.next; }
    curr = curr.next;
  }
  curr.next = l1 ?? l2;
  return dummy.next;
}

// โ”€โ”€โ”€ Remove Nth From End โ€” two-pointer gap trick โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function removeNthFromEnd(head, n) {
  const dummy = new ListNode(0, head);
  let fast = dummy, slow = dummy;
  for (let i = 0; i <= n; i++) fast = fast.next;  // gap of n+1
  while (fast) { fast = fast.next; slow = slow.next; }
  slow.next = slow.next.next;          // skip the nth node
  return dummy.next;
}
Module 04 ยท Foundations
โ— Beginner โ†’ Mid

Stacks & Queues

Stack: Last In First Out (LIFO). Queue: First In First Out (FIFO). Monotonic stack is the most powerful pattern for "next greater element" family of problems โ€” very common in interviews.

04_stack_queue.js
js
// โ”€โ”€โ”€ Valid Parentheses โ€” classic stack problem โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function isValid(s) {
  const stack = [], map = { ')': '(', ']': '[', '}': '{' };
  for (const ch of s) {
    if ('([{'.includes(ch)) stack.push(ch);
    else if (stack.pop() !== map[ch]) return false;
  }
  return stack.length === 0;
}

// โ”€โ”€โ”€ Monotonic Stack โ€” Next Greater Element O(n) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
// TEMPLATE: maintains stack in decreasing order
function nextGreater(nums) {
  const result = new Array(nums.length).fill(-1);
  const stack = [];    // stores INDICES
  for (let i = 0; i < nums.length; i++) {
    while (stack.length && nums[i] > nums[stack.at(-1)]) {
      result[stack.pop()] = nums[i];   // current is next greater for popped
    }
    stack.push(i);
  }
  return result;
}
// Same pattern: Largest Rectangle in Histogram, Daily Temperatures, Stock Span

// โ”€โ”€โ”€ Queue with two stacks (implement queue using stacks) โ”€
class MyQueue {
  in = []; out = [];
  push(x) { this.in.push(x); }
  pop() {
    if (!this.out.length) while (this.in.length) this.out.push(this.in.pop());
    return this.out.pop();
  }
}

// โ”€โ”€โ”€ Sliding Window Maximum โ€” deque O(n) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function maxSlidingWindow(nums, k) {
  const deque = [], result = [];
  for (let i = 0; i < nums.length; i++) {
    if (deque[0] < i - k + 1) deque.shift();  // remove out-of-window
    while (deque.length && nums[deque.at(-1)] < nums[i]) deque.pop();
    deque.push(i);
    if (i >= k - 1) result.push(nums[deque[0]]);
  }
  return result;
}
Module 05 ยท Foundations
โ— Beginner

Hash Maps & Sets

Hash maps are the most powerful tool for reducing time complexity. If you see an O(nยฒ) solution, the fix is usually a HashMap. Every "two-sum" style problem uses this pattern.

05_hashmaps.js
js
// โ”€โ”€โ”€ Two Sum โ€” the canonical HashMap problem O(n) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function twoSum(nums, target) {
  const seen = new Map();   // value โ†’ index
  for (let i = 0; i < nums.length; i++) {
    const complement = target - nums[i];
    if (seen.has(complement)) return [seen.get(complement), i];
    seen.set(nums[i], i);
  }
}
// Key insight: store what you've SEEN, look for what you NEED

// โ”€โ”€โ”€ Frequency counting โ€” group anagrams O(n*k) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function groupAnagrams(strs) {
  const map = new Map();
  for (const s of strs) {
    const key = [...s].sort().join('');   // sorted string = canonical form
    if (!map.has(key)) map.set(key, []);
    map.get(key).push(s);
  }
  return [...map.values()];
}

// โ”€โ”€โ”€ LRU Cache โ€” HashMap + Doubly Linked List O(1) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
class LRUCache {
  constructor(capacity) {
    this.cap = capacity;
    this.map = new Map();  // Map preserves INSERTION ORDER in JS!
  }
  get(key) {
    if (!this.map.has(key)) return -1;
    const val = this.map.get(key);
    this.map.delete(key); this.map.set(key, val); // move to end = most recent
    return val;
  }
  put(key, value) {
    this.map.delete(key);
    if (this.map.size === this.cap) this.map.delete(this.map.keys().next().value);
    this.map.set(key, value);
  }
}
Module 06 ยท Trees & Graphs
โ—† Mid Level

Binary Trees & BST

Tree problems make up 25-30% of coding interview questions. DFS (pre/in/post-order), BFS (level-order), and BST properties are the core patterns. Learn the recursive template and apply it to any tree problem.

06_trees.js โ€” All traversals + classic problems
js
class TreeNode { constructor(val, left=null, right=null) { this.val=val; this.left=left; this.right=right; } }

// โ”€โ”€โ”€ DFS Traversals (recursive) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
const preorder  = node => node ? [node.val, ...preorder(node.left), ...preorder(node.right)] : [];
const inorder   = node => node ? [...inorder(node.left), node.val, ...inorder(node.right)] : [];
const postorder = node => node ? [...postorder(node.left), ...postorder(node.right), node.val] : [];
// BST inorder = SORTED array (crucial property!)

// โ”€โ”€โ”€ BFS / Level Order Traversal โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function levelOrder(root) {
  if (!root) return [];
  const result = [], queue = [root];
  while (queue.length) {
    const level = [], size = queue.length;
    for (let i = 0; i < size; i++) {
      const node = queue.shift();
      level.push(node.val);
      if (node.left) queue.push(node.left);
      if (node.right) queue.push(node.right);
    }
    result.push(level);
  }
  return result;
}

// โ”€โ”€โ”€ Height / Depth O(n) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
const height = node => node ? 1 + Math.max(height(node.left), height(node.right)) : 0;

// โ”€โ”€โ”€ Lowest Common Ancestor (LCA) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function lca(root, p, q) {
  if (!root || root === p || root === q) return root;
  const left = lca(root.left, p, q);
  const right = lca(root.right, p, q);
  return left && right ? root : left ?? right;  // both found = LCA
}

// โ”€โ”€โ”€ Validate BST โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function isValidBST(node, min=-Infinity, max=Infinity) {
  if (!node) return true;
  if (node.val <= min || node.val >= max) return false;
  return isValidBST(node.left, min, node.val) &&
         isValidBST(node.right, node.val, max);
}

// โ”€โ”€โ”€ Diameter of Binary Tree โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function diameterOfBinaryTree(root) {
  let max = 0;
  function depth(node) {
    if (!node) return 0;
    const l = depth(node.left), r = depth(node.right);
    max = Math.max(max, l + r);   // path through this node
    return 1 + Math.max(l, r);    // height from this node
  }
  depth(root); return max;
}
Module 07 ยท Trees & Graphs
โ—† Mid Level

Heaps & Priority Queue

A heap is a complete binary tree where parent is always greater (max-heap) or smaller (min-heap) than children. Used for: Kth largest/smallest, Top K elements, Merge K sorted lists, Median of stream.

Min Heap Properties
Root is the SMALLEST element. Parent โ‰ค children. Insert: O(log n). Extract min: O(log n). Peek min: O(1). Building from array: O(n). Used for: "Kth smallest", scheduling, Dijkstra's shortest path.
O(log n) insertO(1) peek
Max Heap Properties
Root is the LARGEST element. Children โ‰ค parent. Same complexities as min-heap. Used for: "Kth largest", heap sort, priority scheduling. Most "top K" problems use a MIN-heap of size K (counterintuitively).
O(log n) insert
JavaScript Heap (manual)
JS has no built-in PriorityQueue. In interviews: simulate with sorted array for small inputs, or implement min-heap. Many interviewers accept pseudocode for heap operations โ€” ask first.
No built-in in JS
07_heap_patterns.js
js
// โ”€โ”€โ”€ Kth Largest โ€” min-heap of size k โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
// Keep a min-heap. If size > k, pop the min.
// After all elements, root = kth largest.
// O(n log k) time โ€” better than sort O(n log n) for small k

// โ”€โ”€โ”€ Top K Frequent Elements O(n log k) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function topKFrequent(nums, k) {
  const freq = new Map();
  for (const n of nums) freq.set(n, (freq.get(n) ?? 0) + 1);
  // Bucket sort by frequency โ€” O(n) approach!
  const buckets = new Array(nums.length + 1).fill(null).map(() => []);
  freq.forEach((count, num) => buckets[count].push(num));
  const result = [];
  for (let i = buckets.length - 1; i >= 0 && result.length < k; i--)
    result.push(...buckets[i]);
  return result.slice(0, k);
}

// โ”€โ”€โ”€ Median of Data Stream โ€” two heaps trick โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
// Lower half: max-heap (top = max of lower)  
// Upper half: min-heap (top = min of upper)
// Balance sizes: |lowerHeap| - |upperHeap| โ‰ค 1
// Median = avg of tops (even) or top of larger heap (odd)
Module 08 ยท Trees & Graphs
โ—† Mid โ†’ Senior

Graphs, BFS & DFS

Graphs are networks of nodes and edges. Real-world applications: social networks, maps, dependencies. BFS for shortest paths, DFS for exploring all paths. Union-Find for connected components. Topological sort for dependencies.

08_graphs.js โ€” All templates
js
// โ”€โ”€โ”€ Graph representation โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
const graph = new Map();  // adjacency list โ€” most common
graph.set('A', ['B', 'C']);
graph.set('B', ['A', 'D']);

// โ”€โ”€โ”€ BFS โ€” shortest path in UNWEIGHTED graph O(V+E) โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function bfs(graph, start) {
  const visited = new Set([start]);
  const queue = [start];
  while (queue.length) {
    const node = queue.shift();
    for (const neighbor of graph.get(node) ?? []) {
      if (!visited.has(neighbor)) {
        visited.add(neighbor);
        queue.push(neighbor);
      }
    }
  }
}

// โ”€โ”€โ”€ DFS โ€” iterative โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function dfs(graph, start) {
  const visited = new Set(), stack = [start];
  while (stack.length) {
    const node = stack.pop();
    if (visited.has(node)) continue;
    visited.add(node);
    for (const n of graph.get(node) ?? []) stack.push(n);
  }
}

// โ”€โ”€โ”€ Number of Islands โ€” DFS on grid O(m*n) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function numIslands(grid) {
  let count = 0;
  function dfs(r, c) {
    if (r<0||c<0||r>=grid.length||c>=grid[0].length||grid[r][c]!=='1') return;
    grid[r][c] = '0';   // mark visited by mutating
    [[1,0],[-1,0],[0,1],[0,-1]].forEach(([dr,dc]) => dfs(r+dr, c+dc));
  }
  for (let r=0; r<grid.length; r++)
    for (let c=0; c<grid[0].length; c++)
      if (grid[r][c]==='1') { dfs(r,c); count++; }
  return count;
}

// โ”€โ”€โ”€ Topological Sort (Kahn's BFS) โ€” for DAG dependencies โ”€
function topoSort(n, edges) {
  const adj = Array.from({length: n}, () => []);
  const inDegree = new Array(n).fill(0);
  edges.forEach(([u,v]) => { adj[u].push(v); inDegree[v]++; });
  const queue = [], result = [];
  for (let i=0; i<n; i++) if (!inDegree[i]) queue.push(i);
  while (queue.length) {
    const node = queue.shift(); result.push(node);
    for (const next of adj[node]) if (!--inDegree[next]) queue.push(next);
  }
  return result.length === n ? result : [];  // empty = cycle exists
}
Module 09 ยท Algorithms
โ—† Mid Level

Sorting Algorithms

AlgorithmBestAverageWorstSpaceStable?
Bubble SortO(n)O(nยฒ)O(nยฒ)O(1)Yes
Selection SortO(nยฒ)O(nยฒ)O(nยฒ)O(1)No
Insertion SortO(n)O(nยฒ)O(nยฒ)O(1)Yes โ€” good for small/nearly sorted
Merge SortO(n log n)O(n log n)O(n log n)O(n)Yes โ€” stable, predictable
Quick SortO(n log n)O(n log n)O(nยฒ)O(log n)No โ€” fastest in practice
Heap SortO(n log n)O(n log n)O(n log n)O(1)No โ€” guaranteed O(n log n)
Counting SortO(n+k)O(n+k)O(n+k)O(k)Yes โ€” only for integers in range
09_sorting.js โ€” Merge + Quick (must know both)
js
// โ”€โ”€โ”€ Merge Sort โ€” stable, O(n log n) guaranteed โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function mergeSort(arr) {
  if (arr.length <= 1) return arr;
  const mid = arr.length >> 1;
  const left = mergeSort(arr.slice(0, mid));
  const right = mergeSort(arr.slice(mid));
  return merge(left, right);
}
function merge(l, r) {
  const result = []; let i = 0, j = 0;
  while (i < l.length && j < r.length)
    result.push(l[i] <= r[j] ? l[i++] : r[j++]);
  return [...result, ...l.slice(i), ...r.slice(j)];
}

// โ”€โ”€โ”€ Quick Sort โ€” fastest in practice, O(n log n) avg โ”€โ”€โ”€โ”€โ”€
function quickSort(arr, lo=0, hi=arr.length-1) {
  if (lo < hi) {
    const pi = partition(arr, lo, hi);
    quickSort(arr, lo, pi-1);
    quickSort(arr, pi+1, hi);
  }
  return arr;
}
function partition(arr, lo, hi) {
  const pivot = arr[hi]; let i = lo;
  for (let j = lo; j < hi; j++)
    if (arr[j] < pivot) [arr[i++], arr[j]] = [arr[j], arr[i]];
  [arr[i], arr[hi]] = [arr[hi], arr[i]];
  return i;
}
Module 10 ยท Algorithms
โ—† Mid Level

Binary Search โ€” All Variants

Binary search is not just for "find element in sorted array." The pattern extends to: find first/last occurrence, search in rotated array, find answer in a range of values (minimization problems). Master all variants.

10_binary_search.js โ€” All templates
js
// โ”€โ”€โ”€ Template 1: Basic โ€” find exact target โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function search(arr, target) {
  let lo = 0, hi = arr.length - 1;
  while (lo <= hi) {
    const mid = lo + ((hi - lo) >> 1);
    if (arr[mid] === target) return mid;
    arr[mid] < target ? lo = mid + 1 : hi = mid - 1;
  }
  return -1;
}

// โ”€โ”€โ”€ Template 2: Find first position satisfying condition โ”€
function firstTrue(arr, condition) {
  let lo = 0, hi = arr.length - 1, ans = -1;
  while (lo <= hi) {
    const mid = lo + ((hi - lo) >> 1);
    if (condition(arr[mid])) { ans = mid; hi = mid - 1; }  // found, go left for first
    else lo = mid + 1;
  }
  return ans;
}

// โ”€โ”€โ”€ Search in Rotated Sorted Array โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function searchRotated(nums, target) {
  let lo = 0, hi = nums.length - 1;
  while (lo <= hi) {
    const mid = lo + ((hi - lo) >> 1);
    if (nums[mid] === target) return mid;
    if (nums[lo] <= nums[mid]) {   // left half is sorted
      nums[lo] <= target && target < nums[mid] ? hi = mid-1 : lo = mid+1;
    } else {                        // right half is sorted
      nums[mid] < target && target <= nums[hi] ? lo = mid+1 : hi = mid-1;
    }
  }
  return -1;
}

// โ”€โ”€โ”€ Binary search on ANSWER โ€” minimize max / maximize min
// "What is the minimum capacity to ship packages in D days?"
// lo = max(packages), hi = sum(packages)
// Binary search on capacity, check if feasible in D days
// Pattern: can(mid) โ†’ search in answer space, not array space!
๐ŸŽฏ Very common โ€” Google, Amazon, Flipkart
When can you apply binary search to a problem that isn't "find in sorted array"?
Any time the answer space is monotonic โ€” "if X works, then X+1 also works" (or vice versa). Examples: minimum speed to arrive on time, minimum days to make m bouquets, koko eating bananas. The pattern: define the answer range [lo, hi], define a feasibility function canDo(mid), binary search on the answer, find the smallest/largest valid answer. This pattern appears in 30%+ of hard problems.
Module 11 ยท Algorithms
โ—† Mid Level

Two Pointers & Sliding Window

Two of the most powerful O(n) patterns. Two pointers works when elements are sorted or you need to find pairs. Sliding window finds optimal subarrays/substrings with a constraint.

11_two_pointer_sliding.js
js
// โ”€โ”€โ”€ Two Pointers โ€” sorted array pair sum โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function twoSumSorted(nums, target) {
  let lo = 0, hi = nums.length - 1;
  while (lo < hi) {
    const sum = nums[lo] + nums[hi];
    if (sum === target) return [lo, hi];
    sum < target ? lo++ : hi--;
  }
}

// โ”€โ”€โ”€ 3Sum โ€” reduce to 2Sum with outer loop O(nยฒ) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function threeSum(nums) {
  nums.sort((a,b) => a-b); const result = [];
  for (let i = 0; i < nums.length - 2; i++) {
    if (i > 0 && nums[i] === nums[i-1]) continue;  // skip duplicates
    let lo = i+1, hi = nums.length-1;
    while (lo < hi) {
      const sum = nums[i] + nums[lo] + nums[hi];
      if (sum === 0) { result.push([nums[i],nums[lo++],nums[hi--]]); }
      else if (sum < 0) lo++; else hi--;
    }
  }
  return result;
}

// โ”€โ”€โ”€ Sliding Window TEMPLATE โ€” variable size โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function slidingWindow(s, target) {
  let lo = 0, best = Infinity;
  const window = {};  // track window state

  for (let hi = 0; hi < s.length; hi++) {
    // 1. Expand: add s[hi] to window
    window[s[hi]] = (window[s[hi]] ?? 0) + 1;

    // 2. Shrink: while condition violated, remove s[lo] and advance lo
    while (/* condition violated */ false) {
      window[s[lo]]--;
      if (!window[s[lo]]) delete window[s[lo]];
      lo++;
    }
    // 3. Update answer
    best = Math.min(best, hi - lo + 1);
  }
  return best;
}
// Apply to: Minimum Window Substring, Longest Without Repeating,
//           Longest Repeating After Replacement, Fruit Into Baskets
Module 12 ยท Algorithms
โ—ˆ Senior Level

Recursion & Backtracking

Backtracking = recursion + pruning. For every "generate all X" problem: choose, explore, unchoose. The template is the same for all problems โ€” permutations, combinations, subsets, N-Queens, Sudoku.

12_backtracking.js โ€” Universal template
js
// โ”€โ”€โ”€ BACKTRACKING TEMPLATE โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function backtrack(result, current, ...params) {
  if (baseCaseReached) { result.push([...current]); return; }
  for (const choice of choices) {
    current.push(choice);     // CHOOSE
    backtrack(result, current, ...newParams);  // EXPLORE
    current.pop();             // UNCHOOSE (backtrack)
  }
}

// โ”€โ”€โ”€ Permutations โ€” O(n * n!) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function permute(nums) {
  const result = [];
  const bt = (curr, used) => {
    if (curr.length === nums.length) { result.push([...curr]); return; }
    for (let i = 0; i < nums.length; i++) {
      if (used.has(i)) continue;
      curr.push(nums[i]); used.add(i);
      bt(curr, used);
      curr.pop(); used.delete(i);
    }
  };
  bt([], new Set()); return result;
}

// โ”€โ”€โ”€ Subsets โ€” O(n * 2โฟ) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function subsets(nums) {
  const result = [];
  const bt = (start, curr) => {
    result.push([...curr]);
    for (let i = start; i < nums.length; i++) {
      curr.push(nums[i]);
      bt(i + 1, curr);
      curr.pop();
    }
  };
  bt(0, []); return result;
}

// โ”€โ”€โ”€ Combination Sum โ€” O(n^(target/min)) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function combinationSum(candidates, target) {
  const result = [];
  const bt = (start, curr, remaining) => {
    if (remaining === 0) { result.push([...curr]); return; }
    for (let i = start; i < candidates.length; i++) {
      if (candidates[i] > remaining) continue;  // prune!
      curr.push(candidates[i]);
      bt(i, curr, remaining - candidates[i]);    // can reuse same index
      curr.pop();
    }
  };
  candidates.sort((a,b) => a-b);  // sort enables pruning
  bt(0, [], target); return result;
}
Module 13 ยท Dynamic Programming
โ—ˆ Senior โ€” Most Asked

Dynamic Programming

DP = breaking problems into overlapping subproblems + caching. Every DP problem follows two approaches: Top-Down (memoization/recursion) and Bottom-Up (tabulation/iteration). Learn the patterns โ€” there are only a few dozen canonical DP problems.

When to use DP?
1. Optimal substructure: optimal solution built from optimal subproblems. 2. Overlapping subproblems: same subproblems solved multiple times. 3. Problem asks for: count, min, max, yes/no over all possibilities.
Recognition
Top-Down (Memoization)
Write recursive solution first. Add a cache (Map/array). Before computing, check cache. After computing, store in cache. Same time complexity as bottom-up. Easier to think about, harder to see space optimization.
Recursive + cache
Bottom-Up (Tabulation)
Fill a table iteratively from base cases up to target. No recursion stack. Can often optimize space (rolling array). Slightly harder to derive but more common in interviews for cleanliness and space optimization.
Iterative + table
13_dp.js โ€” Core DP patterns + problems
js
// โ”€โ”€โ”€ Fibonacci โ€” both approaches โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
// Top-down:
const memo = new Map();
const fib = n => n <= 1 ? n : (memo.get(n) ?? memo.set(n, fib(n-1) + fib(n-2)) && memo.get(n));
// Bottom-up O(n) time O(1) space:
function fibDP(n) {
  if (n<=1) return n; let [a,b] = [0,1];
  for (let i=2; i<=n; i++) [a,b] = [b, a+b];
  return b;
}

// โ”€โ”€โ”€ 0/1 Knapsack โ€” O(n*W) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function knapsack(weights, values, W) {
  const n = weights.length;
  const dp = new Array(W+1).fill(0);          // space optimized to 1D
  for (let i=0; i<n; i++)
    for (let w=W; w>=weights[i]; w--)           // iterate BACKWARDS for 0/1
      dp[w] = Math.max(dp[w], dp[w-weights[i]] + values[i]);
  return dp[W];
}

// โ”€โ”€โ”€ Longest Common Subsequence O(m*n) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function lcs(s1, s2) {
  const m=s1.length, n=s2.length;
  const dp = Array.from({length:m+1}, () => new Array(n+1).fill(0));
  for (let i=1; i<=m; i++)
    for (let j=1; j<=n; j++)
      dp[i][j] = s1[i-1]===s2[j-1] ? dp[i-1][j-1]+1 : Math.max(dp[i-1][j],dp[i][j-1]);
  return dp[m][n];
}

// โ”€โ”€โ”€ Coin Change โ€” minimum coins O(amount * coins) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function coinChange(coins, amount) {
  const dp = new Array(amount+1).fill(Infinity);
  dp[0] = 0;
  for (const coin of coins)
    for (let i=coin; i<=amount; i++)
      dp[i] = Math.min(dp[i], dp[i-coin]+1);
  return dp[amount] === Infinity ? -1 : dp[amount];
}
DP Categories โ€” know them all: 1D DP: Climbing Stairs, House Robber, Jump Game, Word Break 2D DP: LCS, Edit Distance, Unique Paths, Interleaving String Interval DP: Burst Balloons, Matrix Chain Multiplication Tree DP: Diameter, Max Path Sum, House Robber III Bitmask DP: Shortest Path (TSP), Assign Work to K Workers
Module 14 ยท Algorithms
โ—† Mid Level

Greedy Algorithms

Greedy makes the locally optimal choice at each step hoping to reach the global optimum. Proving a greedy works requires an exchange argument. Classic greedy problems appear in every interview.

When Greedy Works
Greedy works when: a locally optimal choice never needs to be undone (optimal substructure + greedy choice property). Common signals: "minimum cost", "maximum profit", "schedule tasks", "interval problems." Always prove (or at least state) why it works.
Verify first
Interval Scheduling
Sort by end time. Greedily pick intervals that end earliest (leave room for more). Non-overlapping intervals โ†’ O(n log n). Meeting Rooms โ†’ check if sorted end times never overlap with next start.
Sort by end
Jump Game Pattern
Track maximum reachable index. At each position, update max reach. If current index > max reach, unreachable. This O(n) greedy beats the O(nยฒ) DP approach and is the expected answer.
Reach tracking
14_greedy.js
js
// โ”€โ”€โ”€ Activity Selection / Non-overlapping Intervals โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function eraseOverlapIntervals(intervals) {
  intervals.sort((a,b) => a[1]-b[1]);  // sort by END time
  let removed = 0, prevEnd = -Infinity;
  for (const [start, end] of intervals) {
    if (start < prevEnd) removed++;   // overlap โ†’ remove
    else prevEnd = end;               // no overlap โ†’ keep
  }
  return removed;
}

// โ”€โ”€โ”€ Jump Game II โ€” minimum jumps O(n) โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
function jump(nums) {
  let jumps = 0, curEnd = 0, farthest = 0;
  for (let i = 0; i < nums.length - 1; i++) {
    farthest = Math.max(farthest, i + nums[i]);
    if (i === curEnd) { jumps++; curEnd = farthest; }
  }
  return jumps;
}

// โ”€โ”€โ”€ Task Scheduler โ€” greedy with counting โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
// Sort tasks by frequency. Most frequent fills the "frames".
// Answer = max(tasks.length, (maxFreq-1) * (n+1) + tasksWithMaxFreq)
Module 15 ยท Interview Mastersheet

Problem Patterns & Recognition Guide

Pattern Recognition โ€” Given the problem, which technique?
If the problem says...Think...Complexity target
Find pair that sums to XHashMap / Two Pointers (sorted)O(n)
Subarray with max/min sumKadane's / Prefix Sum / Sliding WindowO(n)
Find duplicates / uniqueHashSet / XOR trickO(n)
Search in sorted arrayBinary SearchO(log n)
Kth largest/smallestMin-Heap of size k / QuickSelectO(n log k)
All permutations/subsetsBacktrackingO(n! or 2โฟ)
Count ways / min stepsDynamic ProgrammingO(nยฒ) typical
Tree path / structureDFS recursionO(n)
Shortest path (unweighted)BFSO(V+E)
Shortest path (weighted)Dijkstra's (min-heap)O(E log V)
Next greater elementMonotonic StackO(n)
Longest substring with K charsSliding WindowO(n)
Connected componentsUnion-Find / BFS/DFSO(n ฮฑ(n))
Schedule tasks / orderingTopological SortO(V+E)
Most Asked Problems by Company Level
Must-Know 20 Problems
Two Sum, Valid Parentheses, Merge Intervals, Best Time to Buy Stock, Maximum Subarray, Reverse Linked List, Binary Tree Inorder, Number of Islands, Climbing Stairs, Coin Change, LCS, Word Break, LRU Cache, Meeting Rooms, Jump Game, Top K Frequent, Valid Anagram, Product Except Self, Container With Most Water, 3Sum
All levels
FAANG Favorites
Serialize/Deserialize Binary Tree, Trapping Rain Water, Minimum Window Substring, Sliding Window Maximum, Word Ladder, Alien Dictionary, Burst Balloons, Regular Expression Matching, Largest Rectangle in Histogram, N-Queens, Median of Stream
Hard
Indian Product Co. Favorites
Flipkart: Rotting Oranges, Course Schedule. Swiggy: Shortest Path in Grid. Razorpay: LRU Cache, Design HashMap. Meesho: Two Sum variations, Group Anagrams. Zepto: Merge K Sorted Lists, K Closest Points.
Mid-Senior
๐ŸŽฏ DSA Interview Readiness

You're ready when you can solve these in 20-30 minutes:

  • State time AND space complexity for every solution you write
  • Two Sum in O(n) with HashMap (not brute force O(nยฒ))
  • Reverse a linked list, detect a cycle, find middle node
  • BFS/DFS on a graph, count islands (grid problem)
  • Binary search on sorted array AND on answer space
  • Maximum subarray using Kadane's algorithm
  • Valid parentheses and next greater element (monotonic stack)
  • Write both top-down and bottom-up DP for coin change / climbing stairs
  • Generate all subsets and permutations using backtracking
  • Sliding window for longest substring without repeating chars
  • Level-order traversal of binary tree using BFS