2Brute2Best
🔥0
01

Interval scheduling (Greedy Sub-pattern)

Choose as many non-overlapping intervals as possible (or cut a string into as many parts as possible). Always commit to the interval that frees you up soonest.

Signals in the problem statement
  • ›

    "maximum number of activities / meetings / pairs"

  • ›

    "longest chain" where each pair must start after the previous ends

  • ›

    "partition into as many parts as possible" with a rule per letter

What makes it different

Sort by end, not start or length. Partition Labels has no sort: each letter's last occurrence stretches the current part, and you cut as soon as the part is closed.

Questions

ordered from “learn the idea” to “recognise it without help”
  1. 1
    Activity Selection
    Basic Anchor·GeeksforGeeks
    Easy
  2. 2
    Maximum Length of Pair Chain
    Basic Reinforcement·LeetCode #646
    Medium
  3. 3
    Partition Labels
    Slight Variation·LeetCode #763
    Medium

Template

interval-greedy-template.cpp
// Most non-overlapping intervals: take the one that ends first, again and again.
// Touching ([1,3] then [3,5]) allowed here; use > instead of >= if the problem forbids it.
int maxNonOverlapping(vector<pair<int,int>> iv) {          // {start, end}
    sort(iv.begin(), iv.end(), [](auto& a, auto& b) { return a.second < b.second; });
    int count = 0;
    long long lastEnd = LLONG_MIN;
    for (auto& [s, e] : iv)
        if (s >= lastEnd) { count++; lastEnd = e; }         // fits after the last one taken
    return count;
}

// Partition into most parts: a part must reach the last occurrence of each of its letters.
vector<int> partitionByLast(const string& s) {
    int last[26] = {};
    for (int i = 0; i < (int)s.size(); i++) last[s[i] - 'a'] = i;
    vector<int> sizes;
    int start = 0, end = 0;
    for (int i = 0; i < (int)s.size(); i++) {
        end = max(end, last[s[i] - 'a']);
        if (i == end) { sizes.push_back(end - start + 1); start = i + 1; }   // part closed
    }
    return sizes;
}
Remember this · Greedy
Trigger
Maximise count / minimise cost with a natural "best next step", sorting makes the choice obvious, reachability.
Think
Is there a choice I can always make safely without looking ahead?
Key question
Why can't the greedy choice be worse than the optimal one? (Try to break it with a small example.)