DAY 14 / 30 · WEEK 2 REVIEW

Week 2 Review

Goal of the day

Concept

Week 2 looks like six separate topics, but almost everything reduces to one move: take a problem of size n and shrink it, every step, by throwing away work you can prove doesn't matter. Merge sort shrinks by splitting in half and recombining (Day 10). Quick sort shrinks by partitioning around a pivot so one side never needs to be touched again relative to the other (Day 11). Binary search shrinks by halving a sorted range using one comparison (Day 12), and its variations shrink toward a boundary instead of an exact match (Day 13). Recursion (Day 9) is the mechanism that makes "shrink and repeat" possible without a hand-written loop stack. Even the three O(n²) sorts from Day 8 fit this frame in miniature — they just shrink the unsorted region by one element per pass instead of by half.

The skill this review trains: given a new problem, recognize which kind of shrinking it needs — half the array (search), one side of a partition (quick sort family), or the whole thing split and remerged (merge sort family) — before you write a single line.

Diagram: which Week 2 approach do I reach for?

Sorted array, need an exact match search? Binary Search (Day 12) Need FIRST/LAST occurrence, or a monotonic value check? Search on Answer (Day 13) Problem splits into smaller identical subproblems? Recursion (Day 9) Need guaranteed O(n log n) AND stable order for ties? Merge Sort (Day 10) Need in-place sorting, average-case speed over worst? Quick Sort (Day 11) Small or nearly-sorted array, simplicity over raw speed? Bubble/Selection/ Insertion Sort (Day 8) Check these top to bottom — the first "yes" is usually your pattern. Rows 4-6 assume sorting is actually needed, not just searching.

Interactive visualization: quickselect — sorting and searching combined

Finding the kth largest element blends this week's two biggest ideas: Day 11's partition step (split around a pivot) AND Day 12/13's halving discipline (only chase the ONE side that can contain the answer, throw the rest away without ever recursing into it). That combination drops the average time from quick sort's O(n log n) down to O(n) — you never sort the side you don't need.

current range [lo, hi] pivot comparing to pivot swapped, or eliminated once a round ends found — the answer
Press Play or Step to begin.

Dry run: 2nd largest of [9, 3, 7, 1, 8, 4, 2]

RoundlohipivotPivot's final indexAction
106211 < target(5) → discard indices 0–1, lo=2
226322 < target(5) → discard index 2, lo=3
336744 < target(5) → discard indices 3–4, lo=5
456855 === target(5) → found! Answer = 8

Target index = 7 elements − k(2) = index 5 in ascending sorted order. Four partition rounds, but each round only ever recurses into ONE side — exactly the halving discipline from binary search, just applied to an unsorted partition boundary instead of a sorted midpoint.

Week 2 cheat sheet — code templates

// BUBBLE SORT (Day 8) — O(n) best / O(n²) worst, O(1) space, stable
function bubbleSort(arr) {
  for (let i = 0; i < arr.length - 1; i++) {
    let swapped = false;
    for (let j = 0; j < arr.length - 1 - i; j++) {
      if (arr[j] > arr[j + 1]) {
        [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
        swapped = true;
      }
    }
    if (!swapped) break; // already sorted — stop early
  }
  return arr;
}

// SELECTION SORT (Day 8b) — O(n²) always, O(1) space, NOT stable
function selectionSort(arr) {
  for (let i = 0; i < arr.length - 1; i++) {
    let minIdx = i;
    for (let j = i + 1; j < arr.length; j++) {
      if (arr[j] < arr[minIdx]) minIdx = j;
    }
    if (minIdx !== i) [arr[i], arr[minIdx]] = [arr[minIdx], arr[i]];
  }
  return arr;
}

// INSERTION SORT (Day 8c) — O(n) best / O(n²) worst, O(1) space, stable
function insertionSort(arr) {
  for (let i = 1; i < arr.length; i++) {
    const key = arr[i];
    let j = i - 1;
    while (j >= 0 && arr[j] > key) { arr[j + 1] = arr[j]; j--; }
    arr[j + 1] = key;
  }
  return arr;
}

// MERGE SORT (Day 10) — O(n log n) always, O(n) space, stable
function mergeSort(arr) {
  if (arr.length <= 1) return arr;
  const mid = Math.floor(arr.length / 2);
  const left = mergeSort(arr.slice(0, mid));
  const right = mergeSort(arr.slice(mid));
  return merge(left, right);
}
function merge(left, right) {
  const result = [];
  let i = 0, j = 0;
  while (i < left.length && j < right.length) {
    if (left[i] <= right[j]) result.push(left[i++]);
    else result.push(right[j++]);
  }
  while (i < left.length) result.push(left[i++]);
  while (j < right.length) result.push(right[j++]);
  return result;
}

// QUICK SORT (Day 11) — O(n log n) avg / O(n²) worst, O(log n) space, NOT stable
function quickSort(arr, lo = 0, hi = arr.length - 1) {
  if (lo < hi) {
    const p = partition(arr, lo, hi);
    quickSort(arr, lo, p - 1);
    quickSort(arr, p + 1, hi);
  }
  return arr;
}
function partition(arr, lo, hi) {
  const pivot = arr[hi];
  let i = lo - 1;
  for (let j = lo; j < hi; j++) {
    if (arr[j] <= pivot) { i++; [arr[i], arr[j]] = [arr[j], arr[i]]; }
  }
  [arr[i + 1], arr[hi]] = [arr[hi], arr[i + 1]];
  return i + 1;
}

// BINARY SEARCH — exact match (Day 12) — O(log n), O(1)
function search(nums, target) {
  let lo = 0, hi = nums.length - 1;
  while (lo <= hi) {
    const mid = lo + Math.floor((hi - lo) / 2);
    if (nums[mid] === target) return mid;
    else if (nums[mid] < target) lo = mid + 1;
    else hi = mid - 1;
  }
  return -1;
}

// BINARY SEARCH — narrowing/boundary (Day 13) — O(log n), O(1)
function findBound(nums, target, isFirst) {
  let lo = 0, hi = nums.length - 1, result = -1;
  while (lo <= hi) {
    const mid = lo + Math.floor((hi - lo) / 2);
    if (nums[mid] === target) {
      result = mid;                     // record, then keep narrowing
      if (isFirst) hi = mid - 1; else lo = mid + 1;
    } else if (nums[mid] < target) lo = mid + 1;
    else hi = mid - 1;
  }
  return result;
}

Complexity — everything from Week 2, at a glance

AlgorithmTimeSpaceNote
Bubble / Insertion Sort (Day 8/8c)O(n) best, O(n²) worstO(1)Stable — early-exits on already-sorted input.
Selection Sort (Day 8b)O(n²) alwaysO(1)Not stable — always fully scans, no fast path.
Merge Sort (Day 10)O(n log n) alwaysO(n)Stable, but needs auxiliary arrays to merge into.
Quick Sort (Day 11)O(n log n) avg, O(n²) worstO(log n)In-place, not stable; space is recursion depth.
Binary Search — exact match (Day 12)O(log n)O(1)Needs a sorted array (or a monotonic predicate).
Binary Search — boundary / search on answer (Day 13)O(log n) or O(n log m)O(1)Narrows to a boundary instead of stopping at a match.
Quickselect (today's synthesis)O(n) avg, O(n²) worstO(1) extraRecurses into only the side containing the answer.

Interview corner

How to talk through it out loud: on a mixed problem, name the constraint that decides your algorithm before you name the algorithm — "this needs the array sorted first, and since I also need stability for ties, that pushes me toward merge sort over quick sort" or "this is asking for a boundary, not an exact match, so I need Day 13's narrowing template, not Day 12's." Interviewers are listening for the reasoning chain from constraint to choice, not a memorized algorithm name — that's exactly what separates "I've seen this before" from "I know why this is the right tool."

5 mixed practice problems

1. First Bad Version (Easy — LeetCode: First Bad Version)

You're given n versions [1, 2, ..., n] and an API isBadVersion(version). Once a version is bad, every version after it is also bad. Find the first bad version using as few API calls as possible.

2. Intersection of Two Arrays II (Easy — LeetCode: Intersection of Two Arrays II)

Given two integer arrays, return their intersection — unlike Day 7's version, each shared value must appear in the result as many times as it appears in both arrays.

3. Search a 2D Matrix (Medium — LeetCode: Search a 2D Matrix)

Each row of an m x n matrix is sorted ascending, and the first value of each row is greater than the last value of the previous row. Determine if a target exists, in O(log(m·n)) time.

4. H-Index (Medium — LeetCode: H-Index)

Given a researcher's citation counts, return their h-index: the largest h such that at least h papers have each been cited at least h times.

5. Kth Smallest Element in a Sorted Matrix (Medium — LeetCode: Kth Smallest Element in a Sorted Matrix)

Given an n x n matrix where every row and every column is sorted ascending, find the kth smallest element in the whole matrix.

Quiz

1. Which Week 2 sort is both stable AND guarantees O(n log n) even in the worst case?

2. Quickselect gets its average O(n) time (versus quick sort's O(n log n)) by:

3. What's the key structural difference between Day 12's search() and Day 13's findBound()?

4. For a small, nearly-sorted array where simplicity matters most, which Day 8 sort is the best fit?

5. What property must a "search on answer" feasibility check have — whether it's Koko Eating Bananas or today's Kth Smallest in a Sorted Matrix?