{
  "id": "greedy-dp/greedy",
  "version": 1,
  "deterministic": true,
  "url": "/dsa/greedy-dp/greedy",
  "topic": {
    "slug": "greedy-dp",
    "title": "Greedy & DP"
  },
  "title": "Greedy Algorithms",
  "tagline": "Always take the best-looking option right now — and sometimes that's provably optimal.",
  "vizKind": "bars",
  "complexity": {
    "time": {
      "best": "O(n log n)",
      "average": "O(n log n)",
      "worst": "O(n log n)"
    },
    "space": "O(1)",
    "growth": "nlogn",
    "note": "The sort dominates — n log n — and then a single O(n) pass. Compare that with dynamic programming, which would have to build a table. When greedy is provably safe, it's dramatically simpler and faster."
  },
  "code": {
    "javascript": "// Fit as many meetings as possible into one room.\nfunction maxMeetings(meetings) {\n  // The greedy choice: always take the one that ENDS soonest.\n  meetings.sort((a, b) => a.end - b.end);\n\n  const chosen = [];\n  let lastEnd = 0;\n\n  for (const m of meetings) {\n    if (m.start >= lastEnd) {\n      chosen.push(m);\n      lastEnd = m.end;\n    }\n  }\n  return chosen;\n}",
    "python": "# Fit as many meetings as possible into one room.\ndef max_meetings(meetings):\n    # The greedy choice: always take the one that ENDS soonest.\n    meetings.sort(key=lambda m: m.end)\n\n    chosen = []\n    last_end = 0\n\n    for m in meetings:\n        if m.start >= last_end:\n            chosen.append(m)\n            last_end = m.end\n\n    return chosen\n",
    "java": "// Fit as many meetings as possible into one room.\nList<Meeting> maxMeetings(List<Meeting> meetings) {\n  // The greedy choice: always take the one that ENDS soonest.\n  meetings.sort(Comparator.comparingInt(m -> m.end));\n\n  List<Meeting> chosen = new ArrayList<>();\n  int lastEnd = 0;\n\n  for (Meeting m : meetings) {\n    if (m.start >= lastEnd) {\n      chosen.add(m);\n      lastEnd = m.end;\n    }\n  }\n  return chosen;\n}",
    "cpp": "// Fit as many meetings as possible into one room.\nvector<Meeting> maxMeetings(vector<Meeting> meetings) {\n  // The greedy choice: always take the one that ENDS soonest.\n  sort(meetings.begin(), meetings.end(),\n       [](auto& a, auto& b){ return a.end < b.end; });\n\n  vector<Meeting> chosen;\n  int lastEnd = 0;\n\n  for (auto& m : meetings) {\n    if (m.start >= lastEnd) {\n      chosen.push_back(m);\n      lastEnd = m.end;\n    }\n  }\n  return chosen;\n}"
  },
  "defaultInput": [
    3,
    5,
    8,
    4,
    10,
    6,
    12
  ],
  "defaultTarget": null,
  "inputHint": "Each bar is a meeting's end time, sorted. Green ones got the room.",
  "pitfalls": [
    {
      "wrong": "Assuming greedy works because it feels right.",
      "right": "It needs proof. 'Take the shortest meeting' feels just as sensible as 'take the one ending soonest' — and it's wrong. Without an exchange argument, greedy is only a guess."
    },
    {
      "wrong": "Using greedy on coin change.",
      "right": "With coins 1, 3, 4 and a target of 6, greedy takes 4+1+1 = three coins; the real answer is 3+3 = two. Greedy fails; DP is required."
    },
    {
      "wrong": "Sorting by the wrong key.",
      "right": "For meetings, sort by *end* time, not start time and not duration. The whole correctness rests on that one choice."
    },
    {
      "wrong": "Reconsidering an earlier choice.",
      "right": "Then it isn't greedy any more — that's backtracking or DP. Greedy's speed comes precisely from never looking back."
    }
  ],
  "quiz": [
    {
      "q": "To fit the most meetings into one room, which do you always pick next?",
      "options": [
        "The shortest meeting",
        "The one that starts earliest",
        "The one that ends earliest",
        "A random one"
      ],
      "answer": 2,
      "why": "Ending earliest hands the room back soonest, leaving the most time for everything else. No other choice could ever leave more room — which is why it's provably optimal."
    },
    {
      "q": "When is greedy the wrong tool?",
      "options": [
        "When the input is large",
        "When a locally best choice can lead to a worse overall answer — like coin change with coins 1, 3, 4",
        "When the input is sorted",
        "Greedy is never wrong"
      ],
      "answer": 1,
      "why": "Coins 1, 3, 4 making 6: greedy grabs the 4 and needs three coins; 3+3 needs only two. When the local choice isn't provably safe, you need dynamic programming."
    },
    {
      "q": "What does a greedy algorithm never do?",
      "options": [
        "Sort its input",
        "Look ahead or reconsider a choice it has made",
        "Use a loop",
        "Return the right answer"
      ],
      "answer": 1,
      "why": "It commits at each step and never revisits. That's where its speed comes from — and also why it needs a proof that the commitment is always safe."
    }
  ],
  "problems": [
    {
      "name": "Non-overlapping Intervals",
      "difficulty": "Medium",
      "url": "https://leetcode.com/problems/non-overlapping-intervals/"
    },
    {
      "name": "Jump Game",
      "difficulty": "Medium",
      "url": "https://leetcode.com/problems/jump-game/"
    },
    {
      "name": "Assign Cookies",
      "difficulty": "Easy",
      "url": "https://leetcode.com/problems/assign-cookies/"
    },
    {
      "name": "Minimum Number of Arrows to Burst Balloons",
      "difficulty": "Medium",
      "url": "https://leetcode.com/problems/minimum-number-of-arrows-to-burst-balloons/"
    }
  ],
  "trace": {
    "note": "Each frame is one immutable step: data snapshot, pointers, per-index roles, executing code line, and a one-sentence explanation.",
    "length": 14,
    "frames": [
      {
        "data": [
          {
            "id": "c0-3",
            "value": 3
          },
          {
            "id": "c1-4",
            "value": 4
          },
          {
            "id": "c2-5",
            "value": 5
          },
          {
            "id": "c3-6",
            "value": 6
          },
          {
            "id": "c4-8",
            "value": 8
          },
          {
            "id": "c5-10",
            "value": 10
          },
          {
            "id": "c6-12",
            "value": 12
          }
        ],
        "pointers": [],
        "highlights": [],
        "codeLine": 4,
        "variables": {
          "meetings": 7
        },
        "explanation": "One room, many meetings, and they overlap. Fit in as many as possible. The bars are the meetings, sorted by when they END — and that sort is the entire algorithm.",
        "stats": {
          "comparisons": 0,
          "swaps": 0
        },
        "accent": "active"
      },
      {
        "data": [
          {
            "id": "c0-3",
            "value": 3
          },
          {
            "id": "c1-4",
            "value": 4
          },
          {
            "id": "c2-5",
            "value": 5
          },
          {
            "id": "c3-6",
            "value": 6
          },
          {
            "id": "c4-8",
            "value": 8
          },
          {
            "id": "c5-10",
            "value": 10
          },
          {
            "id": "c6-12",
            "value": 12
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 0
          }
        ],
        "highlights": [
          {
            "index": 0,
            "role": "compare"
          }
        ],
        "codeLine": 10,
        "variables": {
          "start": 2,
          "end": 3,
          "roomFreeAt": 0
        },
        "explanation": "Meeting 2–3: the room is free from 0, so this one fits. Take it.",
        "stats": {
          "comparisons": 1,
          "swaps": 0
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-3",
            "value": 3
          },
          {
            "id": "c1-4",
            "value": 4
          },
          {
            "id": "c2-5",
            "value": 5
          },
          {
            "id": "c3-6",
            "value": 6
          },
          {
            "id": "c4-8",
            "value": 8
          },
          {
            "id": "c5-10",
            "value": 10
          },
          {
            "id": "c6-12",
            "value": 12
          }
        ],
        "pointers": [],
        "highlights": [
          {
            "index": 0,
            "role": "sorted"
          }
        ],
        "codeLine": 12,
        "variables": {
          "booked": 1,
          "roomFreeAt": 3
        },
        "explanation": "Booked. Because we picked the meeting that ends soonest, the room frees up at 3 — as early as it possibly could. That's what leaves the most space for what's left.",
        "stats": {
          "comparisons": 1,
          "swaps": 1
        },
        "accent": "found"
      },
      {
        "data": [
          {
            "id": "c0-3",
            "value": 3
          },
          {
            "id": "c1-4",
            "value": 4
          },
          {
            "id": "c2-5",
            "value": 5
          },
          {
            "id": "c3-6",
            "value": 6
          },
          {
            "id": "c4-8",
            "value": 8
          },
          {
            "id": "c5-10",
            "value": 10
          },
          {
            "id": "c6-12",
            "value": 12
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 1
          }
        ],
        "highlights": [
          {
            "index": 0,
            "role": "sorted"
          },
          {
            "index": 1,
            "role": "compare"
          }
        ],
        "codeLine": 10,
        "variables": {
          "start": 3,
          "end": 4,
          "roomFreeAt": 3
        },
        "explanation": "Meeting 3–4: the room is free from 3, so this one fits. Take it.",
        "stats": {
          "comparisons": 2,
          "swaps": 1
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-3",
            "value": 3
          },
          {
            "id": "c1-4",
            "value": 4
          },
          {
            "id": "c2-5",
            "value": 5
          },
          {
            "id": "c3-6",
            "value": 6
          },
          {
            "id": "c4-8",
            "value": 8
          },
          {
            "id": "c5-10",
            "value": 10
          },
          {
            "id": "c6-12",
            "value": 12
          }
        ],
        "pointers": [],
        "highlights": [
          {
            "index": 0,
            "role": "sorted"
          },
          {
            "index": 1,
            "role": "sorted"
          }
        ],
        "codeLine": 12,
        "variables": {
          "booked": 2,
          "roomFreeAt": 4
        },
        "explanation": "Booked. Because we picked the meeting that ends soonest, the room frees up at 4 — as early as it possibly could. That's what leaves the most space for what's left.",
        "stats": {
          "comparisons": 2,
          "swaps": 2
        },
        "accent": "found"
      },
      {
        "data": [
          {
            "id": "c0-3",
            "value": 3
          },
          {
            "id": "c1-4",
            "value": 4
          },
          {
            "id": "c2-5",
            "value": 5
          },
          {
            "id": "c3-6",
            "value": 6
          },
          {
            "id": "c4-8",
            "value": 8
          },
          {
            "id": "c5-10",
            "value": 10
          },
          {
            "id": "c6-12",
            "value": 12
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 2
          }
        ],
        "highlights": [
          {
            "index": 0,
            "role": "sorted"
          },
          {
            "index": 1,
            "role": "sorted"
          },
          {
            "index": 2,
            "role": "compare"
          }
        ],
        "codeLine": 10,
        "variables": {
          "start": 3,
          "end": 5,
          "roomFreeAt": 4
        },
        "explanation": "Meeting 3–5: the room is busy until 4, so this clashes. Skip it.",
        "stats": {
          "comparisons": 3,
          "swaps": 2
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-3",
            "value": 3
          },
          {
            "id": "c1-4",
            "value": 4
          },
          {
            "id": "c2-5",
            "value": 5
          },
          {
            "id": "c3-6",
            "value": 6
          },
          {
            "id": "c4-8",
            "value": 8
          },
          {
            "id": "c5-10",
            "value": 10
          },
          {
            "id": "c6-12",
            "value": 12
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 3
          }
        ],
        "highlights": [
          {
            "index": 0,
            "role": "sorted"
          },
          {
            "index": 1,
            "role": "sorted"
          },
          {
            "index": 3,
            "role": "compare"
          }
        ],
        "codeLine": 10,
        "variables": {
          "start": 3,
          "end": 6,
          "roomFreeAt": 4
        },
        "explanation": "Meeting 3–6: the room is busy until 4, so this clashes. Skip it.",
        "stats": {
          "comparisons": 4,
          "swaps": 2
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-3",
            "value": 3
          },
          {
            "id": "c1-4",
            "value": 4
          },
          {
            "id": "c2-5",
            "value": 5
          },
          {
            "id": "c3-6",
            "value": 6
          },
          {
            "id": "c4-8",
            "value": 8
          },
          {
            "id": "c5-10",
            "value": 10
          },
          {
            "id": "c6-12",
            "value": 12
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 4
          }
        ],
        "highlights": [
          {
            "index": 0,
            "role": "sorted"
          },
          {
            "index": 1,
            "role": "sorted"
          },
          {
            "index": 4,
            "role": "compare"
          }
        ],
        "codeLine": 10,
        "variables": {
          "start": 5,
          "end": 8,
          "roomFreeAt": 4
        },
        "explanation": "Meeting 5–8: the room is free from 4, so this one fits. Take it.",
        "stats": {
          "comparisons": 5,
          "swaps": 2
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-3",
            "value": 3
          },
          {
            "id": "c1-4",
            "value": 4
          },
          {
            "id": "c2-5",
            "value": 5
          },
          {
            "id": "c3-6",
            "value": 6
          },
          {
            "id": "c4-8",
            "value": 8
          },
          {
            "id": "c5-10",
            "value": 10
          },
          {
            "id": "c6-12",
            "value": 12
          }
        ],
        "pointers": [],
        "highlights": [
          {
            "index": 0,
            "role": "sorted"
          },
          {
            "index": 1,
            "role": "sorted"
          },
          {
            "index": 4,
            "role": "sorted"
          }
        ],
        "codeLine": 12,
        "variables": {
          "booked": 3,
          "roomFreeAt": 8
        },
        "explanation": "Booked. Because we picked the meeting that ends soonest, the room frees up at 8 — as early as it possibly could. That's what leaves the most space for what's left.",
        "stats": {
          "comparisons": 5,
          "swaps": 3
        },
        "accent": "found"
      },
      {
        "data": [
          {
            "id": "c0-3",
            "value": 3
          },
          {
            "id": "c1-4",
            "value": 4
          },
          {
            "id": "c2-5",
            "value": 5
          },
          {
            "id": "c3-6",
            "value": 6
          },
          {
            "id": "c4-8",
            "value": 8
          },
          {
            "id": "c5-10",
            "value": 10
          },
          {
            "id": "c6-12",
            "value": 12
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 5
          }
        ],
        "highlights": [
          {
            "index": 0,
            "role": "sorted"
          },
          {
            "index": 1,
            "role": "sorted"
          },
          {
            "index": 4,
            "role": "sorted"
          },
          {
            "index": 5,
            "role": "compare"
          }
        ],
        "codeLine": 10,
        "variables": {
          "start": 8,
          "end": 10,
          "roomFreeAt": 8
        },
        "explanation": "Meeting 8–10: the room is free from 8, so this one fits. Take it.",
        "stats": {
          "comparisons": 6,
          "swaps": 3
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-3",
            "value": 3
          },
          {
            "id": "c1-4",
            "value": 4
          },
          {
            "id": "c2-5",
            "value": 5
          },
          {
            "id": "c3-6",
            "value": 6
          },
          {
            "id": "c4-8",
            "value": 8
          },
          {
            "id": "c5-10",
            "value": 10
          },
          {
            "id": "c6-12",
            "value": 12
          }
        ],
        "pointers": [],
        "highlights": [
          {
            "index": 0,
            "role": "sorted"
          },
          {
            "index": 1,
            "role": "sorted"
          },
          {
            "index": 4,
            "role": "sorted"
          },
          {
            "index": 5,
            "role": "sorted"
          }
        ],
        "codeLine": 12,
        "variables": {
          "booked": 4,
          "roomFreeAt": 10
        },
        "explanation": "Booked. Because we picked the meeting that ends soonest, the room frees up at 10 — as early as it possibly could. That's what leaves the most space for what's left.",
        "stats": {
          "comparisons": 6,
          "swaps": 4
        },
        "accent": "found"
      },
      {
        "data": [
          {
            "id": "c0-3",
            "value": 3
          },
          {
            "id": "c1-4",
            "value": 4
          },
          {
            "id": "c2-5",
            "value": 5
          },
          {
            "id": "c3-6",
            "value": 6
          },
          {
            "id": "c4-8",
            "value": 8
          },
          {
            "id": "c5-10",
            "value": 10
          },
          {
            "id": "c6-12",
            "value": 12
          }
        ],
        "pointers": [
          {
            "name": "i",
            "index": 6
          }
        ],
        "highlights": [
          {
            "index": 0,
            "role": "sorted"
          },
          {
            "index": 1,
            "role": "sorted"
          },
          {
            "index": 4,
            "role": "sorted"
          },
          {
            "index": 5,
            "role": "sorted"
          },
          {
            "index": 6,
            "role": "compare"
          }
        ],
        "codeLine": 10,
        "variables": {
          "start": 11,
          "end": 12,
          "roomFreeAt": 10
        },
        "explanation": "Meeting 11–12: the room is free from 10, so this one fits. Take it.",
        "stats": {
          "comparisons": 7,
          "swaps": 4
        },
        "accent": "compare"
      },
      {
        "data": [
          {
            "id": "c0-3",
            "value": 3
          },
          {
            "id": "c1-4",
            "value": 4
          },
          {
            "id": "c2-5",
            "value": 5
          },
          {
            "id": "c3-6",
            "value": 6
          },
          {
            "id": "c4-8",
            "value": 8
          },
          {
            "id": "c5-10",
            "value": 10
          },
          {
            "id": "c6-12",
            "value": 12
          }
        ],
        "pointers": [],
        "highlights": [
          {
            "index": 0,
            "role": "sorted"
          },
          {
            "index": 1,
            "role": "sorted"
          },
          {
            "index": 4,
            "role": "sorted"
          },
          {
            "index": 5,
            "role": "sorted"
          },
          {
            "index": 6,
            "role": "sorted"
          }
        ],
        "codeLine": 12,
        "variables": {
          "booked": 5,
          "roomFreeAt": 12
        },
        "explanation": "Booked. Because we picked the meeting that ends soonest, the room frees up at 12 — as early as it possibly could. That's what leaves the most space for what's left.",
        "stats": {
          "comparisons": 7,
          "swaps": 5
        },
        "accent": "found"
      },
      {
        "data": [
          {
            "id": "c0-3",
            "value": 3
          },
          {
            "id": "c1-4",
            "value": 4
          },
          {
            "id": "c2-5",
            "value": 5
          },
          {
            "id": "c3-6",
            "value": 6
          },
          {
            "id": "c4-8",
            "value": 8
          },
          {
            "id": "c5-10",
            "value": 10
          },
          {
            "id": "c6-12",
            "value": 12
          }
        ],
        "pointers": [],
        "highlights": [
          {
            "index": 0,
            "role": "sorted"
          },
          {
            "index": 1,
            "role": "sorted"
          },
          {
            "index": 4,
            "role": "sorted"
          },
          {
            "index": 5,
            "role": "sorted"
          },
          {
            "index": 6,
            "role": "sorted"
          }
        ],
        "codeLine": 16,
        "variables": {
          "booked": 5,
          "total": 7
        },
        "explanation": "5 of 7 meetings fit — and that is provably the most possible. Greedy worked here because \"finish earliest\" is a choice you can never regret. Change the rule to \"take the shortest meeting\" and it breaks.",
        "stats": {
          "comparisons": 7,
          "swaps": 5
        },
        "accent": "sorted"
      }
    ]
  }
}