DSAPrep
MediumGreedy

Gas Station

There are n gas stations along a circular route, where the amount of gas at the ith station is gas[i].

You have a car with an unlimited gas tank and it costs cost[i] of gas to travel from the ith station to its next (i + 1)th station. You begin the journey with an empty tank at one of the gas stations.

Given two integer arrays gas and cost, return the starting gas station's index if you can travel around the circuit once in the clockwise direction, otherwise return -1. If there exists a solution, it is guaranteed to be unique.

Example 1

Input: gas = [1,2,3,4,5], cost = [3,4,5,1,2]
Output: 3
Explanation: Start at station 3, tank = 4. Travel to 4: tank = 4-1+5 = 8. Travel to 0: tank = 8-2+1 = 7. Travel to 1: tank = 7-3+2 = 6. Travel to 2: tank = 6-4+3 = 5. Travel back to 3: exactly enough gas.

Example 2

Input: gas = [2,3,4], cost = [3,4,3]
Output: -1
Explanation: No starting station lets you complete the circuit.

Constraints

  • n == gas.length == cost.length
  • 1 <= n <= 10^5
  • 0 <= gas[i], cost[i] <= 10^4
  • The input is generated such that the answer is unique.
View original on LeetCode β†—

Brute Force

Time O(nΒ²)Space O(1)

Try every station as a starting point and simulate the full lap, bailing out as soon as the tank goes negative.

class Solution:
def canCompleteCircuit(self, gas: list[int], cost: list[int]) -> int:
n = len(gas)
for start in range(n):
tank = 0
steps = 0
i = start
while steps < n:
tank += gas[i] - cost[i]
if tank < 0:
break
i = (i + 1) % n
steps += 1
if steps == n:
return start
return -1

Each of the n candidate starts can simulate up to n steps, so this is O(nΒ²) time in the worst case.

Greedy: One Pass with Reset

OptimalTime O(n)Space O(1)

Two facts make a single pass enough. First, a valid start exists at all only if sum(gas) >= sum(cost) β€” total supply must cover total demand. Second, if starting at station s and driving forward causes the running tank total to first go negative at some station i, then no station between s and i (inclusive) can be a valid start either β€” each of them would arrive at that same failure point with an equal or smaller tank, since starting later only throws away gas s had already banked. So the moment the running total dips below zero, discard every station tried so far and restart the candidate at the very next station.

class Solution:
def canCompleteCircuit(self, gas: list[int], cost: list[int]) -> int:
if sum(gas) < sum(cost):
return -1
total = 0
start = 0
for i in range(len(gas)):
total += gas[i] - cost[i]
if total < 0:
start = i + 1
total = 0
return start

Tracing gas = [1,2,3,4,5], cost = [3,4,5,1,2] (net gas[i] - cost[i] shown in the array):

i
-2
0
-2
1
-2
2
3
3
3
4
total = -2start = 0
1 / 5
resultcurrentdiscarded

net[0] = 1-3 = -2. Running total goes negative β€” station 0 cannot be a valid start. Reset: start = 1.

Why it’s correct: the check sum(gas) >= sum(cost) guarantees some start works; the reset rule guarantees the loop lands on it, because every station that fails is provably not the answer (proven above), so skipping past all of them loses no valid candidate. Complexity: one pass, two running variables β†’ O(n) time, O(1) space.