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”- 1Activity SelectionWalkthroughEasyBasic Anchor·GeeksforGeeks
- 2Maximum Length of Pair ChainWalkthroughMediumBasic Reinforcement·LeetCode #646
- 3Partition LabelsWalkthroughMediumSlight Variation·LeetCode #763
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.)