290. Gas Station
π LeetCode Problem: 134. Gas Station
π Difficulty: Medium
π·οΈ Topics: Array, Greedy
Problem Statement
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 (index 3) and fill up with 4 unit of gas. Your tank = 0 + 4 = 4
Travel to station 4. Your tank = 4 - 1 + 5 = 8
Travel to station 0. Your tank = 8 - 2 + 1 = 7
Travel to station 1. Your tank = 7 - 3 + 2 = 6
Travel to station 2. Your tank = 6 - 4 + 3 = 5
Travel to station 3. The cost is 5. Your gas is just enough to travel back to station 3.
Therefore, return 3 as the starting index.
Example 2:
Input: gas = [2,3,4], cost = [3,4,3]
Output: -1
Explanation:
You can't start at station 0 or 1, as there is not enough gas to travel to the next station.
Let's start at station 2 and fill up with 4 unit of gas. Your tank = 0 + 4 = 4
Travel to station 0. Your tank = 4 - 3 + 2 = 3
Travel to station 1. Your tank = 3 - 3 + 3 = 3
Travel to station 2. Your tank = 3 - 4 = -1. You cannot travel back to station 2, as it requires 4 unit of gas but you only have 3.
Therefore, you can't travel around the circuit once no matter where you start.
Constraints:
- n == gas.length == cost.length
- 1 <= n <= 10^5
- 0 <= gas[i], cost[i] <= 10^4
π³ Visual Understanding - The Gas Station Problem
The Problem We're Solving:
Circular route with n gas stations:
Station 0
β cost[0]
Station 1
β cost[1]
Station 2
β cost[2]
...
β cost[n-2]
Station n-1
β cost[n-1]
(back to Station 0)
At each station i:
- Fill up gas[i] units
- Need cost[i] units to reach next station
Question: From which station can we complete the circuit?
Understanding the Journey:
Example: gas = [1,2,3,4,5], cost = [3,4,5,1,2]
Station 0: gas=1, cost to next=3
ββ[1]ββ
β β need 3
Station 1: gas=2, cost to next=4
ββ[2]ββ
β β need 4
Station 2: gas=3, cost to next=5
ββ[3]ββ
β β need 5
Station 3: gas=4, cost to next=1
ββ[4]ββ
β β need 1
Station 4: gas=5, cost to next=2
ββ[5]ββ
β β need 2
(back to Station 0)
Net gain/loss at each station:
Station 0: 1 - 3 = -2 (lose 2)
Station 1: 2 - 4 = -2 (lose 2)
Station 2: 3 - 5 = -2 (lose 2)
Station 3: 4 - 1 = +3 (gain 3) β
Station 4: 5 - 2 = +3 (gain 3) β
Key Observations:
1. CIRCULAR route
After station n-1, you return to station 0
2. Start with EMPTY tank
Tank = 0 initially
3. Must complete ENTIRE circuit
Visit all n stations and return to start
4. At each station:
Tank = (previous tank) + gas[i] - cost[i]
Must have Tank >= 0 at all times!
5. If solution exists, it's UNIQUE
Only ONE starting station works
π§ The AHA Moment - Why Greedy Works
The Brute Force Observation:
Try every station as starting point:
For station 0: Simulate complete journey
For station 1: Simulate complete journey
For station 2: Simulate complete journey
...
This is O(nΒ²) - too slow for n = 10^5! π°
The Key Insights:
Insight 1: Total Gas Must Be Enough
For ANY solution to exist:
sum(gas) must be >= sum(cost)
Why?
Total gas available = sum(gas)
Total gas needed = sum(cost)
If sum(gas) < sum(cost):
β Not enough gas in total!
β No starting point will work! β
This is a NECESSARY condition!
Insight 2: The Greedy Choice
If we start from station A and can't reach station B:
β ANY station between A and B also can't reach B!
Why?
If starting from A, we run out before B
β We had extra gas accumulated from A
β Starting from middle (say C) has LESS gas than starting from A
β So C definitely can't reach B either!
Therefore: If we fail at station B starting from A,
next try should start from B+1, not A+1!
This is the GREEDY insight! π―
Insight 3: Single Pass Solution
Because of Insight 2:
- Try starting from station 0
- If we fail at station k, next start = k+1
- Keep going...
- If we reach end, the last start position is answer!
Only ONE pass needed! O(n)! β¨
Visual Discovery of Greedy Property:
gas = [1, 2, 3, 4, 5]
cost = [3, 4, 5, 1, 2]
net = [-2,-2,-2,+3,+3]
Try starting from station 0:
Station 0: tank = 0 + 1 = 1
Travel to 1: 1 - 3 = -2 β (FAILED!)
Can't reach station 1 from station 0.
KEY OBSERVATION:
Starting from 0, we had tank=1
Still couldn't reach station 1 (needed 3)
If we start from station 0 with 0 tank and fail,
there's NO WAY starting from between 0 and 1 will work!
(We'd have even less gas!)
So next try: start from station 1!
Try starting from station 1:
Station 1: tank = 0 + 2 = 2
Travel to 2: 2 - 4 = -2 β (FAILED!)
Can't reach station 2 from station 1.
SAME LOGIC:
Starting from 1 with accumulated gas couldn't reach 2
So no point trying anything between 0 and 2
Next try: start from station 2!
Try starting from station 2:
Station 2: tank = 0 + 3 = 3
Travel to 3: 3 - 5 = -2 β (FAILED!)
Next try: start from station 3!
Try starting from station 3:
Station 3: tank = 0 + 4 = 4
Travel to 4: tank = 4 - 1 = 3 β
Station 4: tank = 3 + 5 = 8
Travel to 0: tank = 8 - 2 = 6 β
Station 0: tank = 6 + 1 = 7
Travel to 1: tank = 7 - 3 = 4 β
Station 1: tank = 4 + 2 = 6
Travel to 2: tank = 6 - 4 = 2 β
Station 2: tank = 2 + 3 = 5
Travel to 3: tank = 5 - 5 = 0 β
Reached starting point! Answer: 3 β
π΄ Approach 1: Brute Force Simulation
π Function Definition
Function Signature:
int canCompleteCircuit(int[] gas, int[] cost)
What it does: - Try EACH station as starting point - For each start, simulate the entire journey - If journey completes, return that starting station - If no station works, return -1
π‘ Intuition
"Try every possible starting station"
For each station i as start:
Simulate journey starting from i
Keep track of gas tank
If tank ever goes negative β this start doesn't work
If complete circuit β found answer!
Straightforward but slow!
π Implementation
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int n = gas.length;
// Try each station as starting point
for (int start = 0; start < n; start++) {
if (canCompleteFromStart(gas, cost, start)) {
return start;
}
}
return -1; // No solution
}
private boolean canCompleteFromStart(int[] gas, int[] cost, int start) {
int n = gas.length;
int tank = 0;
// Simulate journey starting from 'start'
for (int count = 0; count < n; count++) {
int station = (start + count) % n; // Circular index
// Fill gas at current station
tank += gas[station];
// Travel to next station
tank -= cost[station];
// If tank goes negative, can't proceed
if (tank < 0) {
return false;
}
}
return true; // Completed circuit!
}
}
π Dry Run: gas = [1,2,3,4,5], cost = [3,4,5,1,2]
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
TRY START = 0
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
tank = 0
Station 0: tank = 0 + 1 - 3 = -2 β
Can't proceed! Return false.
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
TRY START = 1
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
tank = 0
Station 1: tank = 0 + 2 - 4 = -2 β
Can't proceed! Return false.
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
TRY START = 2
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
tank = 0
Station 2: tank = 0 + 3 - 5 = -2 β
Can't proceed! Return false.
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
TRY START = 3
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
tank = 0
Station 3: tank = 0 + 4 - 1 = 3 β
Station 4: tank = 3 + 5 - 2 = 6 β
Station 0: tank = 6 + 1 - 3 = 4 β
Station 1: tank = 4 + 2 - 4 = 2 β
Station 2: tank = 2 + 3 - 5 = 0 β
Completed circuit! Return true.
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
RESULT: Start = 3 β
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
π Complexity Analysis
Time Complexity: O(nΒ²)
Outer loop: Try n starting points
Inner loop: Simulate n stations for each start
Total: O(n) Γ O(n) = O(nΒ²)
Too slow for n = 10^5! β οΈ
Space Complexity: O(1)
Only using variables, no extra arrays
π’ Approach 2: Greedy - One Pass Solution (Optimal)
π¨ Building Deep Intuition - Understanding WHY Greedy Works
Let me show you the greedy insight with DETAILED reasoning:
Step 1: The Fundamental Total Gas Check
Before trying to find a starting station, ask:
"Is there enough total gas to complete the circuit?"
Total gas available: sum(gas) = gas[0] + gas[1] + ... + gas[n-1]
Total gas needed: sum(cost) = cost[0] + cost[1] + ... + cost[n-1]
If sum(gas) < sum(cost):
β Not enough gas in the entire system!
β No matter where you start, you'll run out!
β Return -1 immediately!
If sum(gas) >= sum(cost):
β Enough gas exists in total!
β A solution MUST exist!
β Now we just need to FIND where to start!
This check is CRUCIAL! π
Step 2: The Core Greedy Insight - With Detailed Example
Let me show you WHY the greedy approach works with a clear example:
gas = [1, 3, 2, 4, 5]
cost = [2, 1, 5, 1, 2]
Attempt 1: Start from Station 1
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
JOURNEY: Station 1 β Station 2 β Station 3
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
At Station 1 (START):
Tank: 0 (empty start)
Fill: gas[1] = 3
Tank after fill: 0 + 3 = 3
Travel Station 1 β Station 2:
Cost: cost[1] = 1
Tank after travel: 3 - 1 = 2 β (Success! Reached Station 2)
At Station 2:
Tank: 2 (arrived with 2 from Station 1)
β THIS IS BONUS GAS!
Fill: gas[2] = 2
Tank after fill: 2 + 2 = 4
Travel Station 2 β Station 3:
Cost: cost[2] = 5
Tank after travel: 4 - 5 = -1 β (FAILED! Can't reach Station 3)
RESULT: Starting from Station 1, we CANNOT reach Station 3!
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
The Key Question: Should We Try Station 2?
Let's compare TWO scenarios side by side:
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
SCENARIO A: Starting from Station 1 (what we just tried)
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
Station 1:
Tank: 0 (start)
Fill: +3
Tank: 3
Travel to Station 2 (cost 1):
Tank: 3 - 1 = 2
Station 2:
Tank: 2 (arrived with 2 units from Station 1 - BONUS!)
Fill: +2
Tank: 4 (we have 4 units leaving Station 2)
Travel to Station 3 (cost 5):
Tank: 4 - 5 = -1 β FAILED!
Key Point: We had 4 units when leaving Station 2
But 4 < 5, so we FAILED!
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
SCENARIO B: Starting from Station 2 (should we try this?)
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
Station 2:
Tank: 0 (fresh start - NO BONUS!)
Fill: +2
Tank: 2 (we have only 2 units leaving Station 2)
Travel to Station 3 (cost 5):
Tank: 2 - 5 = -3 β FAILED!
Key Point: We have only 2 units when leaving Station 2
But 2 < 5, so we FAILED even worse!
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
THE COMPARISON - THE AHA MOMENT! π―
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
Gas when leaving Station 2 Can reach Station 3?
β β
Scenario A: 4 units NO (4 < 5)
Scenario B: 2 units NO (2 < 5)
If 4 units wasn't enough to reach Station 3,
how can 2 units (which is LESS) be enough?
IMPOSSIBLE!
Therefore: Don't waste time trying Station 2!
We already know it will fail!
The Reasoning - Why Station 2 Will Definitely Fail
Think about what happened:
When we started from Station 1:
1. We began with empty tank (0 units)
2. We filled at Station 1 (got 3 units)
3. We traveled to Station 2 (spent 1 unit)
4. We arrived at Station 2 with 2 units in tank
5. This 2 units is EXTRA gas we brought from Station 1!
6. We filled at Station 2 (got 2 more units)
7. Total at Station 2: 2 (carried) + 2 (filled) = 4 units
8. We tried to reach Station 3 (needs 5 units)
9. We FAILED because 4 < 5
Now imagine starting fresh from Station 2:
1. We begin with empty tank (0 units)
2. We fill at Station 2 (got 2 units)
3. Total at Station 2: 0 (carried) + 2 (filled) = 2 units
4. We try to reach Station 3 (needs 5 units)
5. We will FAIL because 2 < 5
The difference:
Starting from Station 1: We had BONUS of 2 units from the journey
Starting from Station 2: We have NO BONUS (starting fresh)
With bonus, we had 4 units β Failed
Without bonus, we have 2 units β Will definitely fail!
CONCLUSION: If we can't reach Station 3 from Station 1 (with accumulated gas),
we definitely can't reach Station 3 from Station 2 (without accumulated gas)!
So skip Station 2 entirely!
Next try: Station 3!
Step 3: The General Greedy Rule
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
THE GREEDY PROPERTY (Now you understand WHY!)
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
If you start from station A and fail to reach station B:
β You had accumulated gas from the journey A to B-1
β Even with this accumulated gas, you couldn't reach B
β Any station between A and B-1 has LESS accumulated gas than you did
β So they will ALL fail to reach B too!
Therefore:
β Skip ALL stations from A to B-1
β Next starting candidate: Station B itself!
This is the GREEDY insight that reduces O(nΒ²) to O(n)! π―
Visual Analogy - The Running Start
Think of it like running and jumping over a gap:
Scenario A: Starting from Station 1
Station 1 Station 2 Station 3
(Start) (Checkpoint) (Destination)
β β β
β β β
βββrunning startββββ€ β
(momentum!) βββββtry to jumpββββββββββ€
(you have speed from β
running from 1!) β
β Still can't make it!
Scenario B: Starting from Station 2
Station 2 Station 3
(Start from (Destination)
standstill)
β β
β β
βββββtry to jumpββββββββββ€
(you have NO speed, β
starting fresh!) β
β Even worse!
If you can't make the jump WITH a running start (momentum),
you definitely can't make it starting from a standstill!
This is why we skip Station 2 when we fail from Station 1! π
Step 4: The Complete Algorithm
Algorithm Logic:
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
1. CHECK TOTAL BALANCE:
If sum(gas) < sum(cost):
β Not enough gas total
β Return -1 immediately
2. FIND STARTING STATION:
start = 0 (try starting from station 0)
tank = 0 (empty tank)
For each station i from 0 to n-1:
a. Calculate net gain/loss: tank += (gas[i] - cost[i])
b. If tank goes negative:
- Can't reach station i+1 from current start
- By greedy property: ALL stations from start to i also can't reach i+1
- So set start = i+1 (skip all failed stations)
- Reset tank = 0
3. RETURN ANSWER:
Return start
Why no verification needed?
- We checked sum(gas) >= sum(cost), so solution EXISTS
- We ruled out all other stations via greedy property
- The last 'start' we set is THE answer!
π Implementation - Now You Understand It!
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int n = gas.length;
// STEP 1: Check if solution is even possible
int totalGas = 0;
int totalCost = 0;
for (int i = 0; i < n; i++) {
totalGas += gas[i];
totalCost += cost[i];
}
if (totalGas < totalCost) {
return -1; // Not enough gas in total - impossible!
}
// STEP 2: Find the starting station
// (We know solution exists because totalGas >= totalCost)
int start = 0; // Current starting candidate
int tank = 0; // Current gas in tank
for (int i = 0; i < n; i++) {
// Add gas at station i, subtract cost to travel to i+1
tank += gas[i] - cost[i];
// If tank goes negative, we can't reach station i+1 from current start
if (tank < 0) {
// By greedy property: ALL stations from 'start' to 'i' will fail
// So next candidate is i+1
start = i + 1;
tank = 0; // Reset tank for new start
}
}
return start;
}
}
π Complete Dry Run With Understanding
gas = [1, 2, 3, 4, 5]
cost = [3, 4, 5, 1, 2]
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
STEP 1: Total Balance Check
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
totalGas = 1 + 2 + 3 + 4 + 5 = 15
totalCost = 3 + 4 + 5 + 1 + 2 = 15
totalGas >= totalCost? YES (15 >= 15)
β Solution EXISTS! Now find where to start...
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
STEP 2: Find Starting Station
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
start = 0
tank = 0
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
i = 0: gas[0]=1, cost[0]=3
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
tank = 0 + (1 - 3) = -2
Tank negative! β
Understanding:
Started from Station 0 with empty tank
Filled 1 unit at Station 0
Need 3 units to reach Station 1
Only have 1 unit β Can't reach Station 1!
Greedy Decision:
Station 0 failed to reach Station 1
So Station 0 won't work!
Next candidate: start = 1
Reset: tank = 0
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
i = 1: gas[1]=2, cost[1]=4
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
tank = 0 + (2 - 4) = -2
Tank negative! β
Understanding:
Started from Station 1 with empty tank
Filled 2 units at Station 1
Need 4 units to reach Station 2
Only have 2 units β Can't reach Station 2!
Greedy Decision:
Station 1 failed to reach Station 2
So Stations 0 and 1 both won't work!
Next candidate: start = 2
Reset: tank = 0
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
i = 2: gas[2]=3, cost[2]=5
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
tank = 0 + (3 - 5) = -2
Tank negative! β
Understanding:
Started from Station 2 with empty tank
Filled 3 units at Station 2
Need 5 units to reach Station 3
Only have 3 units β Can't reach Station 3!
Greedy Decision:
Station 2 failed to reach Station 3
So Stations 0, 1, 2 all won't work!
Next candidate: start = 3
Reset: tank = 0
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
i = 3: gas[3]=4, cost[3]=1
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
tank = 0 + (4 - 1) = 3
Tank positive! β
Understanding:
Started from Station 3 with empty tank
Filled 4 units at Station 3
Need 1 unit to reach Station 4
Have 4 units β Can reach Station 4!
After travel: 4 - 1 = 3 units remaining
No action needed, continue with start = 3
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
i = 4: gas[4]=5, cost[4]=2
βββββββββββββββββββββββββββββββββββββββββββββββββββββββ
tank = 3 + (5 - 2) = 6
Tank positive! β
Understanding:
At Station 4 with 3 units from previous travel
Filled 5 units at Station 4
Total: 3 + 5 = 8 units
Need 2 units to reach Station 0 (circular)
After travel: 8 - 2 = 6 units remaining
No action needed, continue with start = 3
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
RESULT
βββββββββββββββββββββββββββββββββββββββββββββββββββββ
start = 3
Return 3 β
Why this is correct:
- Stations 0, 1, 2 were ruled out (tank went negative)
- From Station 3, tank stayed positive through end
- Total balance is positive, so solution exists
- By greedy property, Station 3 is THE answer!
No need to verify by simulating full circuit!
The greedy property guarantees it works! β¨
π― Why No Verification Needed - The Beautiful Proof
Question: "Why don't we need to verify the answer by simulating the full circuit?"
Answer:
We proved two things:
1. SOLUTION EXISTS:
sum(gas) >= sum(cost)
β There's enough gas in total
β SOME starting station must work
2. ALL OTHER STATIONS RULED OUT:
Stations 0, 1, 2 were ruled out (tank went negative)
β They can't complete the circuit
3. ONLY ONE CANDIDATE LEFT:
Station 3 is the only candidate left
β By elimination, it MUST be the answer!
4. WHY CIRCULAR PART WORKS:
From Station 3 to end: tank = 6 (surplus!)
From Station 0 to 2: net = (1-3) + (2-4) + (3-5) = -6 (deficit)
Surplus (6) exactly covers deficit (-6)!
β We can complete the circular part!
This is the beauty of the greedy approach:
- Total balance check ensures solution exists
- Greedy elimination finds the unique solution
- No verification needed! π―
π Complexity Analysis
Time Complexity: O(n)
Pass 1: Calculate total gas and cost β O(n)
Pass 2: Find starting station β O(n)
Total: O(n)
OPTIMAL! Can't do better than O(n)! β¨
Space Complexity: O(1)
Only using a few variables
No extra arrays or data structures
Constant space!
π‘ Alternative Greedy Implementation
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int n = gas.length;
int totalSurplus = 0; // Total gas surplus
int currentSurplus = 0; // Surplus from current start
int start = 0;
for (int i = 0; i < n; i++) {
int surplus = gas[i] - cost[i];
totalSurplus += surplus;
currentSurplus += surplus;
// If current surplus negative, reset start
if (currentSurplus < 0) {
start = i + 1;
currentSurplus = 0;
}
}
// Check if solution exists
return totalSurplus >= 0 ? start : -1;
}
}
This version: - Calculates total surplus while finding start - Slightly more elegant - Same complexity: O(n) time, O(1) space
π― Key Insights Summary
The Three Critical Points:
1. Total Gas Check
sum(gas) >= sum(cost) β Solution exists
sum(gas) < sum(cost) β No solution possible
This is NECESSARY and SUFFICIENT!
2. The Greedy Property
If you fail at station B starting from A:
β All stations from A to B-1 also fail
β Next try: start from B
This eliminates O(nΒ²) redundant checks!
3. Single Pass Sufficiency
Because solution is UNIQUE (if it exists):
β One pass to rule out stations
β Last candidate is THE answer
β No need to verify!
π Quick Revision Notes
π― Core Concept
Problem: Find starting gas station to complete circular route
Key Observation: If sum(gas) >= sum(cost), solution exists and is unique
Greedy Strategy: 1. Check total gas vs total cost 2. Scan once: if tank goes negative, move start forward 3. Return final start position
Why It Works: - Failing from A to B means all A to B-1 also fail - Total balance ensures remaining part is completable
β‘ Quick Implementation
import java.util.Arrays;
public class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
// return naive(gas, cost);
return greedy(gas, cost);
}
private int greedy(int[] gas, int[] cost) {
// step 1: immediate check (cost should be always less than gas)
int sumGas = Arrays.stream(gas).sum();
int sumCost = Arrays.stream(cost).sum();
if (sumCost > sumGas) {
return -1;
}
// step 2: start from station 0 and proceed till
// you cannot reach next station
int fuelSpent = 0;
int startStation = 0;
for (int currStation = 0; currStation < gas.length; currStation++) {
fuelSpent = fuelSpent + gas[currStation] - cost[currStation];
// step 3: once you cannot move next station (when fuelSpent < 0), we
// need to start from the next station (like we are trying every station
// in the naive method)
// Suppose, we started at station 0 and got fuel spent -ve at station 3
// We need to reset fuel spent and startStation becomes 4.
// Why start will not become any of 1, 2 or 3?
// Greedy concept: If we are not able to reach station 3 from station 0, we
// cannot reach from any of other stations like 1 or 2.
// If we see formula:
// fuelSpent = fuelSpent + gas[currStation] - cost[currStation]
// fuelSpent adds +ve. station 0 already adds extra gas.
// If with that only, we are not able to means, we cannot do with station 1 or 2
if (fuelSpent < 0) {
fuelSpent = 0;
startStation = currStation + 1;
}
}
return startStation;
}
private int naive(int[] gas, int[] cost) {
int n = gas.length;
// step 1: start trying from every station
// check if we can complete the circuit starting from this station
for (int station = 0; station < n; station++) {
if (canComplete(gas, cost, station)) {
return station;
}
}
return -1;
}
private boolean canComplete(int[] gas, int[] cost, int station) {
int n = gas.length;
int fuelSpent = 0;
// step 2: go station by station from the current station
for (int i = 0; i < n; i++) {
int currStation = (station + i) % n;
// step 3: fuel spent to travel from this station
// to next station (i to i + 1)
fuelSpent = fuelSpent + gas[currStation] - cost[currStation];
// step 4: return immediately if not possible
if (fuelSpent < 0) {
return false;
}
}
return true;
}
public static void main(String[] args) {
Solution s = new Solution();
System.out.println(s.canCompleteCircuit(new int[] { 1, 2, 3, 4, 5 }, new int[] { 3, 4, 5, 1, 2 }) == 3);
}
}
π Key Points
β CIRCULAR route (after last station, back to first)
β Check total gas >= total cost FIRST
β If solution exists, it's UNIQUE
β Greedy: move start forward when tank negative
β ONE pass sufficient (O(n))
β No need to verify answer (guaranteed by total balance)
πͺ Memory Aid
"Total balance check first!"
"Tank negative? Move start forward!"
"One pass finds the unique answer!"
"Greedy works because failures eliminate ranges!" β¨
β οΈ Common Mistakes
// Mistake 1: Not checking total first
for (int start = 0; start < n; start++) {
// Try each start...
}
// β Wastes time if solution doesn't exist!
// β CORRECT: Check first
if (sum(gas) < sum(cost)) return -1;
// Mistake 2: Moving start by 1 instead of to failure point
if (tank < 0) {
start++; // β Wrong! Still O(nΒ²)
}
// β CORRECT: Jump to failure point
if (tank < 0) {
start = i + 1; // Skip all stations up to failure
}
// Mistake 3: Trying to verify the answer
// β No need! If total balance is positive and we found start,
// it's guaranteed to work!
// Mistake 4: Not resetting tank
if (tank < 0) {
start = i + 1;
// β Forgot to reset tank!
}
// β CORRECT
if (tank < 0) {
start = i + 1;
tank = 0; // Reset!
}
π Practice Exercises
Exercise 1: Trace Yourself
Trace the greedy algorithm on:
gas = [2,3,4]
cost = [3,4,3]
totalGas = ?
totalCost = ?
Solution exists? ?
i=0: tank=?, start=?
i=1: tank=?, start=?
i=2: tank=?, start=?
Answer: ?
(Solution: No solution exists, return -1)
Exercise 2: Edge Cases
What's the answer for these?
1. gas = [5], cost = [4]
Answer: ?
2. gas = [2], cost = [2]
Answer: ?
3. gas = [1,2,3,4,5], cost = [5,4,3,2,1]
Answer: ?
(Solutions: 0, 0, 0)
π Congratulations!
You've mastered the Gas Station problem!
What You Learned:
β
Brute Force - Try all starts O(nΒ²)
β
Greedy Optimization - One pass O(n)
β
Total Balance - Necessary and sufficient condition
β
Greedy Property - Failure eliminates ranges
β
Proof of Correctness - Why greedy works
The Beautiful Insight:
Complex Problem β Simple Greedy Solution
Two key insights:
1. Total gas check tells us IF solution exists
2. Greedy scan tells us WHERE the solution is
The magic:
Failing at position B from start A means:
ALL positions A to B-1 also fail!
This single insight reduces O(nΒ²) to O(n)!
This is the power of Greedy:
Find the property that eliminates redundant work
One clever observation β Massive speedup! π―
Interview Mastery:
When asked about Gas Station:
1. Understand the problem: "Circular route, find starting station"
2. Brute force: "Try each station - O(nΒ²)"
3. Key insight: "Check total gas first!
If sum(gas) < sum(cost), no solution"
4. Greedy insight: "If fail at B from A,
all A to B-1 also fail. Jump to B!"
5. Code it: Clean O(n) solution
6. Explain correctness: "Total balance + greedy property
guarantee the answer"
Shows deep understanding! π―
You've mastered an elegant greedy algorithm! πβ¨π―