You drive a circular route of n gas stations. If the total gas covers the total cost, a unique valid starting station is guaranteed. One greedy pass finds it: reset the start candidate to i+1 every time the running tank dips negative.
You are given two arrays gas and cost of length n. You drive a car in a circle: starting at station i you collect gas[i] litres and spend cost[i] to reach station (i+1)%n. Return the index of the starting station that lets you complete the full loop, or -1 if none exists. The answer is guaranteed unique if it exists.
Worked example. gas=[1,2,3,4,5], cost=[3,4,5,1,2]. The net gains are [-2,-2,-2,3,3]. Starting at station 3: tank goes 3→6→4→2→0 — never negative. Answer: 3.
sum(gas) ≥ sum(cost) then a valid start is guaranteed to exist and is unique. To find it, scan left to right tracking a running currentTank. The moment it goes negative, every station from the original start up through i is disqualified (they all accumulate the same deficit). Reset start = i+1 and currentTank = 0. Whatever is left after the full scan is the answer — no second pass needed.totalTank=0, currentTank=0, start=0. The first two track overall feasibility and local viability; the last tracks the current candidate.i, compute net = gas[i] - cost[i] and add it to both tanks. The total tank keeps the global sum; the current tank tests the run from start.currentTank < 0, set start = i + 1 and reset currentTank = 0. Any station in the discarded range would carry the same deficit forward — none of them can be the answer.start if totalTank ≥ 0, else -1. The global check catches infeasibility; the local scan found the unique valid start.i+1 skip intermediate stations safely? Because if starting at j (for any j between the old start and i) already accumulates a smaller prefix than starting at start, it would run out even sooner. The deficit at i proves every station in [start, i] fails — not just start.The greedy approach works because the problem guarantees at most one valid start; that uniqueness is what lets us commit to i+1 without backtracking. Space is O(1) — just three scalars.
gas=[1,2,3,4,5], cost=[3,4,5,1,2]. Net gain at each station = gas[i]-cost[i]. Initialise totalTank=0, currentTank=0, start=0.1function canCompleteCircuit(gas: number[], cost: number[]): number {2▶ let totalTank = 0;3▶ let currentTank = 0;4▶ let start = 0;56 for (let i = 0; i < gas.length; i++) {7 const net = gas[i] - cost[i];8 totalTank += net;9 currentTank += net;1011 // Can't reach the next station from the current start candidate.12 // Any start in [start, i] is ruled out — reset to i+1.13 if (currentTank < 0) {14 start = i + 1;15 currentTank = 0;16 }17 }1819 // If total gas < total cost, the circuit is impossible.20 return totalTank >= 0 ? start : -1;21}
function canCompleteCircuit(gas: number[], cost: number[]): number {
let totalTank = 0;
let currentTank = 0;
let start = 0;
for (let i = 0; i < gas.length; i++) {
const net = gas[i] - cost[i];
totalTank += net;
currentTank += net;
// Can't reach the next station from the current start candidate.
// Any start in [start, i] is ruled out — reset to i+1.
if (currentTank < 0) {
start = i + 1;
currentTank = 0;
}
}
// If total gas < total cost, the circuit is impossible.
return totalTank >= 0 ? start : -1;
}totalTank will hold the running sum of all net gains (used only for the feasibility check at the end). currentTank tracks gas remaining since the last reset of start. start is the current best candidate for the answer.net = gas[i] - cost[i] is the station's contribution. Adding it to both tanks is the key move: the total keeps the global picture; the current tank tests the run from start.currentTank means we can't reach station i+1 from start. More importantly, any intermediate station would also fail (proven by the prefix argument). So we jump start to i+1 and clear the running tank.totalTank < 0, total gas is insufficient globally; no start works. Otherwise the unique valid start is exactly start— the last index we didn't have to abandon.n stations. O(1) space — only three integer variables regardless of input size.start fails at i, any j ∈ (start, i] begins with a partial prefix that is strictly smaller (it misses the positive contribution of earlier stations) — so it also fails at or before i.totalTank ≥ 0 — use a small epsilon tolerance.function canCompleteCircuit(gas: number[], cost: number[]): number {
let totalTank = 0;
let currentTank = 0;
let start = 0;
for (let i = 0; i < gas.length; i++) {
const net = gas[i] - cost[i];
totalTank += net;
currentTank += net;
// Can't reach the next station from the current start candidate.
// Any start in [start, i] is ruled out — reset to i+1.
if (currentTank < 0) {
start = i + 1;
currentTank = 0;
}
}
// If total gas < total cost, the circuit is impossible.
return totalTank >= 0 ? start : -1;
}n stations. O(1) space — only three integer variables regardless of input size.Try each station as the start and simulate the full circular loop; the first start whose tank never dips below zero is the answer. The literal "just try them all" baseline.
function canCompleteCircuit(gas: number[], cost: number[]): number {
const n = gas.length;
for (let start = 0; start < n; start++) {
let tank = 0;
let ok = true;
// Drive the whole circle, visiting all n stations wrapping around.
for (let step = 0; step < n; step++) {
const i = (start + step) % n;
tank += gas[i] - cost[i];
if (tank < 0) { ok = false; break; } // can't reach the next station
}
if (ok) return start;
}
return -1;
}O(n²) and times out on long routes. The greedy pass uses the fact that a deficit at i rules out every start in [start, i] at once, so a single O(n) scan suffices.| circular route, choose a start index | greedy start reset |
| running sum goes negative → discard prefix | Kadane / gas-station reset |
| total sum feasibility check + single-pass find | totalTank + currentTank pattern |
| "complete the circuit" or "lap the array" | greedy reset to i+1 |
function canCompleteCircuit(gas: number[], cost: number[]): number {
let totalTank = 0;
let currentTank = 0;
let start = 0;
for (let i = 0; i < gas.length; i++) {
const net = gas[i] - cost[i];
totalTank += net;
currentTank += net;
if (currentTank < 0) {
start = i + 1;
currentTank = 0;
}
}
return totalTank >= 0 ? start : -1;
}sum(gas) ≥ sum(cost) a valid start exists and is unique. Find it by resetting start = i+1 whenever currentTank goes negative.gas=[1,2,3,4,5], cost=[3,4,5,1,2]. What does the algorithm return?gas=[2,3,4], cost=[3,4,3]. What does the algorithm return?