Read-only web browser

Solutions

Browse the interview solutions folder with syntax highlighting.

gas-station.py

greedy/gas-station.py · Python · 2.5 KiB · 2026-04-14 08:10

Back to folder
# Brute force, greedy or 2 pointers. Greedy: keep track of gas balance, if it becomes negative we can't start from any of the preceding stations, so we move the start pointer to the next station and reset the balance. 2 pointers: one from the end and one from the start, move the end pointer until we run out of gas, then move the start pointer until we have gas again, repeat until they meet. 
# greedy

# Greedy (sort of Kadane's algorithm applied to gas[i]-cost[i] array) - O(n) time, O(1) space
def canCompleteCircuit(gas: list[int], cost: list[int]) -> int:
    if sum(gas) < sum(cost):
        return -1
    # else: we know there is one (only one) solution

    tank = 0 # gas balance
    start_i = 0
    for i in range(len(gas)):
        tank += (gas[i] - cost[i])
        if tank < 0:
            tank = 0
            start_i = (i + 1) % len(gas)
    # we don't need to loop back from the beginning
    # because we know that only 1 solution exists, so it must be it
    # as we already excluded all the preceding positions

    return start_i

"""By visualizing this process, we can see that it involves dividing our journey
into segments, each of which ends in a "valley" station where the accumulated gas becomes negative.
These segments cannot be crossed with 0 initial gas, and any station within them is not a valid starting station.

By design: acc_gas_seg1 + acc_gas_seg2 + acc_gas_seg3 >= 0
So if acc_gas_seg1 and acc_gas_seg2 are negative, acc_gas_se3 will be positive
and will allow to finish the circle, so we don't need to loop the circle back from the beginning.
"""

# 2 pointers - O(n) time, O(1) space
def canCompleteCircuit(gas: list[int], cost: list[int]) -> int:
    n = len(gas)
    # 2 pointers:
    # - start: from the end goes towards start <---
    # - end: from start goes towards end --->
    start, end = n - 1, 0
    tank = gas[start] - cost[start]
    while start > end:
        if tank < 0:
            start -= 1
            tank += gas[start] - cost[start]
        else:
            tank += gas[end] - cost[end]
            end += 1
    return start if tank >= 0 else -1
    
# Brute force - O(n^2) time, O(1) space
def canCompleteCircuit(gas: list[int], cost: list[int]) -> int:
    n = len(gas)

    for i in range(len(gas)):
        tank = gas[i] - cost[i]
        if tank < 0:
            continue

        j = (i + 1) % n
        while j != i:
            tank += (gas[j] - cost[j])
            if tank < 0:
                break

            j = (j+1) % n

        if j == i:
            return i

    return -1