MediumArrays & Strings

Gas Station โ€” Solution

Problem

There are N gas stations arranged in a circle. At each station you can collect some fuel, and travelling to the next station burns a fixed amount. Starting with an empty tank, find the index of the station from which you can complete the full loop โ€” or return -1 if no valid starting point exists.

  • Input: gas = [1, 2, 3, 4, 5], cost = [3, 4, 5, 1, 2]
  • Output: 3
  • Explanation: Starting at station 3, you collect enough fuel at each stop to complete the full loop without your tank ever going negative.

Counter-example: gas = [2, 3, 4], cost = [3, 4, 3] โ†’ -1. The total fuel (9) equals total cost (10), so the circuit is physically impossible regardless of starting point.

Intuition

At each station, your tank gains or loses gas[i] - cost[i] net fuel. If the sum of all net values is negative, the trip is impossible โ€” there simply isn't enough total fuel. Otherwise, a valid starting point is guaranteed to exist and is unique. The key greedy insight: the moment your running tank goes negative, every station you've passed since the last reset is already disqualified as a starting point (they all begin with less accumulated fuel than you had), so the next candidate must be the very next station.

Approach 1 โ€” Brute Force

For each station as a candidate start, simulate the full circuit and check whether the tank ever goes negative.

  1. For each station start from 0 to n-1, initialize tank = 0
  2. Simulate n steps starting from start, wrapping around with modulo
  3. At each step add gas[station] - cost[station] to the tank
  4. If the tank ever drops below zero, this start fails โ€” break and try the next
  5. If all n steps complete without the tank going negative, return start
  6. If no start works, return -1
1def canCompleteCircuit(gas: list[int], cost: list[int]) -> int:
2    n = len(gas)
3    for start in range(n):
4        tank = 0
5        valid = True
6        for step in range(n):
7            station = (start + step) % n
8            tank += gas[station] - cost[station]
9            if tank < 0:
10                valid = False
11                break
12        if valid:
13            return start
14    return -1

Time: O(nยฒ) โ€” each of n candidate starts may require simulating up to n steps.
Space: O(1) โ€” only a running tank and loop indices.

Approach 2 โ€” Greedy Single Pass

If your running tank goes negative at station i, every station from the current start through i is eliminated as a candidate โ€” they all began with less accumulated fuel than you had, so they'd fail even sooner at station i. Reset the candidate start to i + 1 and keep a separate total_surplus to detect the overall impossible case.

  1. Initialize total_surplus = 0, current_surplus = 0, start = 0
  2. For each station i, compute net = gas[i] - cost[i] and add to both variables
  3. If current_surplus < 0, set start = i + 1 and reset current_surplus = 0
  4. After the full pass, if total_surplus < 0 the circuit is impossible โ€” return -1
  5. Otherwise return start (guaranteed to be the unique valid answer)
1def canCompleteCircuit(gas: list[int], cost: list[int]) -> int:
2    total_surplus = 0
3    current_surplus = 0
4    start = 0
5
6    for i in range(len(gas)):
7        net = gas[i] - cost[i]
8        total_surplus += net
9        current_surplus += net
10
11        if current_surplus < 0:
12            # Every station from previous start through i is disqualified
13            start = i + 1
14            current_surplus = 0
15
16    return start if total_surplus >= 0 else -1

Time: O(n) โ€” a single linear pass with no inner loop.
Space: O(1) โ€” three scalar variables regardless of input size.

Complexity Summary

ApproachTimeSpaceWhen to use
Brute ForceO(nยฒ)O(1)Debugging or verifying correctness on tiny inputs
Greedy Single PassO(n)O(1)Always โ€” same constant space with linear time

Common Mistakes

  • Filtering starts by gas[i] >= cost[i] โ€” a station doesn't need to cover its own cost; surplus fuel accumulated from previous stops can make it viable even with a local deficit.
  • Setting start = i instead of start = i + 1 when current_surplus goes negative โ€” the station where you ran out is itself invalid; the new candidate is the very next one.
  • Returning start unconditionally without checking total_surplus >= 0 โ€” if total fuel is less than total cost, the greedy still sets a start value but the circuit is impossible.
  • Running a second verification pass after the greedy selects a candidate โ€” the greedy guarantee is mathematical: if total_surplus >= 0, the returned start is provably correct.
  • Applying % n modulo inside the greedy loop โ€” the greedy's single forward pass handles the circular structure implicitly through total_surplus; modulo arithmetic is only needed in the brute force.

Related Problems

  • Jump Game โ€” same greedy pattern: scan linearly and track whether a goal remains reachable
  • Jump Game II โ€” extends the reachability greedy to minimize the number of jumps taken
  • Partition Labels โ€” greedy with reset: commit to a partition the moment a boundary condition triggers
  • Minimum Size Subarray Sum โ€” sliding window that advances one pointer greedily once a condition is satisfied
  • Best Time to Buy and Sell Stock โ€” running minimum scan with an implicit "reset" at each new low, same single-pass greedy flavor

Ready to practice? Try it on SkillFlow

Adaptive problems, AI follow-up interviews, and a skill score that shows exactly where you need to improve.

Practice This Problem โ†’