Problem. gas stations around a circle. Station has fuel, and travelling from to costs . Starting with an empty tank, from which station can you complete the circuit?

The greedy

int canCompleteCircuit(const vector<int>& gas, const vector<int>& cost) {
    long long total = 0, tank = 0;
    int start = 0;
    for (int i = 0; i < (int)gas.size(); i++) {
        long long diff = gas[i] - cost[i];
        total += diff;
        tank  += diff;
        if (tank < 0) { start = i + 1; tank = 0; }    // restart from the next station
    }
    return total >= 0 ? start : -1;
}

One pass, space.

Why it works

Two claims.

  1. A solution exists iff . Necessity is clear. Sufficiency follows from claim 2.

  2. If the tank goes negative while travelling from to , then no station in can be the start. Suppose were a valid start. Starting from , the tank was non-negative on arrival at (otherwise we would have restarted earlier), so a run from has no more fuel than the run from had at — and that run failed by station . So fails too.

Therefore restarting at never skips a valid answer, and one pass suffices. ∎

The structure is identical to Kadane’s reset rule: once the running total goes negative, discard the whole prefix.

The prefix-sum view

Let and . Starting at works iff every rotated prefix sum stays non-negative, which happens exactly when

So the valid start is just after the global minimum prefix, which is another way to see the same answer — and it generalises to “find all valid starts” (all positions achieving the minimum, when ties exist).

The general pattern: circular arrays

TechniqueWhen
Duplicate the array ( length)windows or subarrays that may wrap
Minimum prefix rotation”find a starting point such that all prefixes are valid”
Total minus the complementcircular max subarray =
Fix one element in or outcircular DP; solve twice
Modular indexingsmall circular scans

The gas station problem is the cleanest instance of the second row — and that reformulation (“which rotation makes all prefix sums non-negative”) appears in bracket-matching, in scheduling with deadlines, and in the cycle lemma.

The cycle lemma

For a sequence of integers summing to , exactly of the rotations have all prefix sums positive.

For this says there is a unique valid rotation — which is why the gas station answer is unique when it exists, and it is also the combinatorial proof of the Catalan and ballot formulas.

Variants

VariantMethod
Find all valid startspositions achieving the minimum prefix
Minimum starting fuel needed
With a tank capacity limitgreedy fails; use a DP or a sliding window
Refuelling with a limited number of stopsgreedy with a max-heap of passed stations
Non-circular (a straight road)prefix sums with a running minimum
Multiple vehiclesa different problem entirely

Minimum refuelling stops

“Reach a target with a tank of size , minimising stops.” Drive as far as possible; whenever you run out, retroactively refuel at the largest station passed so far (a max-heap). Greedy, , and provably optimal by an exchange argument — the same “take everything, discard the worst” shape as job sequencing.

Why it is worth knowing

It teaches the prefix-sum reset argument: when a running total goes negative, the entire prefix can be discarded because nothing inside it can be a valid start. That one observation turns an “try every start” into , and it recurs in Kadane, in bracket matching, and in circular scheduling.

See also: Kadane’s Algorithm · Prefix Sum · Exchange Arguments