Skip to the notes
JSGroundwork
JSGroundwork handwritten · web dev
✎Playground→⌘Problems↻Review🔥Progress

Chapters

34 chapters
⌕
Beginner10›
B1Complexity analysisB2Arrays & stringsB3HashingB4Two pointersB5Sliding windowB6Binary searchB7Sorting algorithmsB8Stacks & queuesB9Linked listsB10Basic recursion
Intermediate12›
I1TreesI2Tree problems in depthI3Heaps & priority queuesI4Graphs: representationI5Graph problemsI6BacktrackingI7DP: 1DI8DP: 2DI9Greedy algorithmsI10IntervalsI11Bit manipulationI12Matrix problems
Advanced12›
A1Advanced DPA2Union-FindA3Advanced graph algorithmsA4Minimum Spanning TreeA5TriesA6Segment & Fenwick treesA7String algorithmsA8Monotonic stack & queueA9Design problemsA10Advanced backtrackingA11Topological patternsA12Interview strategy
/ search[ ] chaptert top

DSA in JS levels

1Beginner2Intermediate3Advanced

Ready to read

JSJavaScript⑂Git◎Interview prepΣDSA in JSSDSystem Design
More topics15›
</>HTML{ }CSS⚛ReactNNext.jsNeNest.jsTSTypeScriptNoNode.js🐳DockerDBSQL & Databases✓Testing🔒Web Security☁Cloud & DevOps◈GraphQL◆Redis☸Kubernetes
100%
I9

Greedy algorithms

The best DP alternative — when the locally best choice happens to be globally best too.

The trade greedy makes

DP explores every relevant option and keeps whichever turns out best. Greedy skips that entirely: at each step, take whatever looks best right now, commit to it, and never reconsider. That's a huge shortcut when it works — usually O(n log n) instead of DP's O(n²) or worse — but it only produces the correct answer for problems with a specific mathematical property.

The property that has to hold: the greedy-choice property

A problem is safe for greedy only if a locally optimal choice is always part of some globally optimal solution — choosing it never closes off the best overall answer. If that's not provably true, greedy will find a valid answer, just not always the best one, and it will fail silently — no error, just a wrong result on some input you didn't test.

⚠ Greedy's biggest risk: it "works" on your test cases and fails in the interview follow-up The interviewer's next question is almost always "can you prove that's optimal?" or a counter-example that breaks it. If you can't argue why the greedy choice is always safe, say so explicitly and fall back to DP — guessing greedy without justification is a bigger red flag than just using DP from the start.

Worked example: Activity/Interval scheduling

Maximize the number of non-overlapping intervals you can select. The greedy choice: always take the interval that finishes earliest among the remaining valid options.

A (picked) B (conflicts with A) C (picked) D (conflicts with C) E (picked) F (picked)
Sort by finish time, always take the next interval that starts after the last one you picked ends.
function maxNonOverlapping(intervals) {
  intervals.sort((a, b) => a[1] - b[1]); // sort by FINISH time — the entire trick

  let count = 0, lastEnd = -Infinity;
  for (const [start, end] of intervals) {
    if (start >= lastEnd) { // this one doesn't conflict with our last pick
      count++;
      lastEnd = end;
    }
  }
  return count;
}

Why finish time and not start time or duration: picking whatever finishes earliest leaves the maximum possible room for everything that comes after — any other choice can only leave equal or less room. That's the actual proof sketch, and being able to say it is what separates "I memorized this" from "I understand why it's safe."

Worked example: Jump Game — can you reach the end?

function canJump(nums) {
  let farthestReachable = 0;
  for (let i = 0; i < nums.length; i++) {
    if (i > farthestReachable) return false; // stuck — can't even reach index i
    farthestReachable = Math.max(farthestReachable, i + nums[i]);
  }
  return true;
}

The greedy insight: you never need to know which path gets you furthest, only the single number "furthest index reachable so far" — tracking every possible path (which DP would do) is unnecessary work because only the maximum ever matters for future decisions.

Worked example: Gas Station

function canCompleteCircuit(gas, cost) {
  let total = 0, tank = 0, start = 0;
  for (let i = 0; i < gas.length; i++) {
    const diff = gas[i] - cost[i];
    total += diff;
    tank += diff;
    if (tank < 0) {       // can't reach the next station from any point up to here
      start = i + 1;       // so the answer, if any, must start AFTER i
      tank = 0;
    }
  }
  return total >= 0 ? start : -1; // total < 0 means no valid start exists anywhere
}

This one's greedy argument is subtler: if the tank goes negative arriving at station i, starting from any station between the current start and i would also fail, because each of those partial sums was non-negative up to the point of failure — so it's always safe to jump the candidate start forward to i + 1 without missing a valid answer.

Greedy vs DP — how to decide which one a problem wants

SignalPoints toward
"Maximum/minimum number of X" with a simple, provable local ruleGreedy
You can sort by one property and process in that orderGreedy
The best choice now can make a later choice worse in a way you can't undoDP
You keep wanting to say "but what if I hadn't picked that one"DP — that's the tell you need to explore alternatives
Say it like this → "I'll try the greedy approach — sort by finish time and always take the next non-conflicting option — and I can justify it because taking the earliest-finishing option never leaves less room than any other choice would, so it can't cost us a better solution."

Recognizing it in an unseen problem

  • "Minimum number of," "maximum number of," where a sorted, greedy-order decision seems natural
  • You can articulate why the greedy choice never eliminates the optimal answer — if you can't, don't trust it
  • Scheduling, interval, and "assign resources" problems are greedy's home turf
  • When in doubt in an interview: try to prove greedy for a minute; if you can't, say so and switch to DP rather than silently guessing
Practice this layer

Opens in the editor — write it, run it, and check it against real tests.

Gas Station5 tests · advancedJump Game5 tests · intermediateJump Game II5 tests · advancedCandy5 tests · advancedPartition Labels5 tests · intermediate
←previousDP: 2D↑ CovernextIntervals→