217. Gas Station Circuit
Problem
Given equally sized nonnegative gas and cost lists, return a station index from which one full clockwise circuit is possible with an initially empty, unlimited-capacity tank. At station i receive gas[i], then spend cost[i] to reach the next station. Return -1 if impossible or empty. Use the candidate-reset rule for deterministic selection.
Examples
Example 1
gas_station([1,2,3,4,5],[3,4,5,1,2])
=> 3Station 3 begins a feasible circuit after the failed prefix.
Example 2
gas_station([2,3,4],[3,4,3])
=> -1The total available fuel is insufficient.
Example 3
gas_station([0],[0])
=> 0A zero-cost singleton circuit is feasible.
Reveal the worked solution and reasoning
Why this mechanism works
Track global surplus separately from the current candidate's tank. If the candidate fails at i, every station between that candidate and i also fails: their skipped prefix had nonnegative surplus, so starting later cannot repair the negative remainder to i. Discard that entire block and try i+1.
State and boundaries
total is the whole processed surplus. tank is the surplus from candidate through the current station; every earlier candidate in discarded blocks has been disproved.
Protocol
- Reject empty input.
- Add gas[i]-cost[i] to total and tank.
- When tank<0 move candidate to i+1 and reset tank.
- Return candidate if total>=0, otherwise -1.
Visualization
net [-2,-2,-2,3,3]
failed blocks move candidate to 1,2,3
total=0; start 3 survives the suffix and wraparoundPython implementation
def gas_station(gas, cost):
if not gas:
return -1
total = tank = candidate = 0
for i in range(len(gas)):
surplus = gas[i] - cost[i]
total += surplus
tank += surplus
if tank < 0:
candidate = i + 1
tank = 0
return candidate if total >= 0 else -1
Worked execution
gas_station([1,2,3,4,5],[3,4,5,1,2])
L2 gas_station: if not gas: gas=[1, 2, 3, 4, 5]; cost=[3, 4, 5, 1, 2] L4 gas_station: total = tank = candidate = 0 gas=[1, 2, 3, 4, 5]; cost=[3, 4, 5, 1, 2]; total=0; tank=0; candidate=0 L5 gas_station: for i in range(len(gas)): gas=[1, 2, 3, 4, 5]; cost=[3, 4, 5, 1, 2]; total=0; tank=0; candidate=0; i=0 L6 gas_station: surplus = gas[i] - cost[i] gas=[1, 2, 3, 4, 5]; cost=[3, 4, 5, 1, 2]; total=0; tank=0; candidate=0; i=0; surplus=-2 L7 gas_station: total += surplus gas=[1, 2, 3, 4, 5]; cost=[3, 4, 5, 1, 2]; total=-2; tank=0; candidate=0; i=0; surplus=-2 L8 gas_station: tank += surplus gas=[1, 2, 3, 4, 5]; cost=[3, 4, 5, 1, 2]; total=-2; tank=-2; candidate=0; i=0; surplus=-2 L10 gas_station: candidate = i + 1 gas=[1, 2, 3, 4, 5]; cost=[3, 4, 5, 1, 2]; total=-2; tank=-2; candidate=1; i=0; surplus=-2 L11 gas_station: tank = 0 gas=[1, 2, 3, 4, 5]; cost=[3, 4, 5, 1, 2]; total=-2; tank=0; candidate=1; i=0; surplus=-2 ... 13 intermediate state changes omitted ... L8 gas_station: tank += surplus gas=[1, 2, 3, 4, 5]; cost=[3, 4, 5, 1, 2]; total=-3; tank=3; candidate=3; i=3; surplus=3 L5 gas_station: for i in range(len(gas)): gas=[1, 2, 3, 4, 5]; cost=[3, 4, 5, 1, 2]; total=-3; tank=3; candidate=3; i=4; surplus=3 L7 gas_station: total += surplus gas=[1, 2, 3, 4, 5]; cost=[3, 4, 5, 1, 2]; total=0; tank=3; candidate=3; i=4; surplus=3 L8 gas_station: tank += surplus gas=[1, 2, 3, 4, 5]; cost=[3, 4, 5, 1, 2]; total=0; tank=6; candidate=3; i=4; surplus=3
Result: 3. Station 3 begins a feasible circuit after the failed prefix.
gas_station([2,3,4],[3,4,3])
L2 gas_station: if not gas: gas=[2, 3, 4]; cost=[3, 4, 3] L4 gas_station: total = tank = candidate = 0 gas=[2, 3, 4]; cost=[3, 4, 3]; total=0; tank=0; candidate=0 L5 gas_station: for i in range(len(gas)): gas=[2, 3, 4]; cost=[3, 4, 3]; total=0; tank=0; candidate=0; i=0 L6 gas_station: surplus = gas[i] - cost[i] gas=[2, 3, 4]; cost=[3, 4, 3]; total=0; tank=0; candidate=0; i=0; surplus=-1 L7 gas_station: total += surplus gas=[2, 3, 4]; cost=[3, 4, 3]; total=-1; tank=0; candidate=0; i=0; surplus=-1 L8 gas_station: tank += surplus gas=[2, 3, 4]; cost=[3, 4, 3]; total=-1; tank=-1; candidate=0; i=0; surplus=-1 L10 gas_station: candidate = i + 1 gas=[2, 3, 4]; cost=[3, 4, 3]; total=-1; tank=-1; candidate=1; i=0; surplus=-1 L11 gas_station: tank = 0 gas=[2, 3, 4]; cost=[3, 4, 3]; total=-1; tank=0; candidate=1; i=0; surplus=-1 ... 5 intermediate state changes omitted ... L5 gas_station: for i in range(len(gas)): gas=[2, 3, 4]; cost=[3, 4, 3]; total=-2; tank=0; candidate=2; i=2; surplus=-1 L6 gas_station: surplus = gas[i] - cost[i] gas=[2, 3, 4]; cost=[3, 4, 3]; total=-2; tank=0; candidate=2; i=2; surplus=1 L7 gas_station: total += surplus gas=[2, 3, 4]; cost=[3, 4, 3]; total=-1; tank=0; candidate=2; i=2; surplus=1 L8 gas_station: tank += surplus gas=[2, 3, 4]; cost=[3, 4, 3]; total=-1; tank=1; candidate=2; i=2; surplus=1
Result: -1. The total available fuel is insufficient.
Why the solution is correct
A negative total makes any full circuit impossible. Each failed block eliminates all its possible starts by the prefix-surplus argument. The final candidate lies after a minimum cumulative-prefix boundary, so all subsequent cyclic partial sums are nonnegative when total is nonnegative. It therefore completes the circuit.
Time and space
O(n) time and O(1) auxiliary state.
Common mistakes
Resetting total with tank discards the global feasibility condition. A finite tank capacity changes the surplus argument.
Reasoning card
State: total is the whole processed surplus. tank is the surplus from candidate through the current station; every earlier candidate in discarded blocks has been disproved.
Invariant: Total surplus determines global feasibility.
Decision to rehearse: If running tank fails at i, no start since the current candidate can work.
Finish: Return candidate if total>=0, otherwise -1
Transfer exercise
Return every feasible start using prefix sums and a sliding minimum over a doubled surplus array.