05
Running balance / local rules (Greedy Sub-pattern)
Walk the input once with a running balance or a local rule; a failure tells you exactly which earlier choices are impossible.
Signals in the problem statement
- ›
"circular route", "gas station"
- ›
"give change" with a few note types
- ›
"each child with a higher rating than a neighbour gets more"
- ›
"no two adjacent" placements
What makes it different
Running total + restart (Gas Station). Keep the more flexible resource (Lemonade: keep fives). Rules on both sides → two passes, left then right, take the max (Candy).
Questions
ordered from “learn the idea” to “recognise it without help”- 1Lemonade ChangeWalkthroughEasyBasic Anchor·LeetCode #860
- 2Can Place FlowersWalkthroughEasyBasic Reinforcement·LeetCode #605
- 3Gas StationWalkthroughMediumSlight Variation·LeetCode #134
- 4CandyWalkthroughHardMedium·LeetCode #135
Template
balance-template.cpp
// Circular route: net[i] = gain at i minus cost to go on. Return a start index or -1.
int startOfCircuit(const vector<int>& net) {
long long total = 0, tank = 0;
int start = 0;
for (int i = 0; i < (int)net.size(); i++) {
total += net[i];
tank += net[i];
if (tank < 0) { start = i + 1; tank = 0; } // no start in start..i can pass i
}
return total < 0 ? -1 : start;
}
// Rules on both neighbours: one pass for each side, then take the max.
long long twoPassMin(const vector<int>& r) { // Candy
int n = r.size();
vector<int> c(n, 1);
for (int i = 1; i < n; i++) if (r[i] > r[i - 1]) c[i] = c[i - 1] + 1;
for (int i = n - 2; i >= 0; i--) if (r[i] > r[i + 1]) c[i] = max(c[i], c[i + 1] + 1);
return accumulate(c.begin(), c.end(), 0LL);
}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.)