Asked 3 months ago
0Comments
3 Views
The Gas Station problem is a classic algorithmic challenge that tests one's ability to think about circular data structures and optimize for efficiency. we'll dive deep into three different approaches to solve this problem, discussing the logic, implementation, and time complexity of each.
Imagine you’re on a circular road trip with a bunch of gas stations along the way. Each station has a certain amount of gas (let’s say in liters), and it takes a certain amount of gas to travel to the next station (let’s say in kilometers).
The question is: Can you complete the entire trip starting from any gas station, and if so, from which one?
means....
Your task is to find the starting station index from which you can complete a full circle of the gas stations. If no such station exists, return -1
.
Given two arrays:
gas[i]
= Amount of gas at the ith station.cost[i]
= Gas needed to get from the ith station to the (i+1)th station.Here’s how it works:
gas
and cost
.-1
.Let’s break down the example to understand what’s happening.
gas = [1, 2, 3, 4, 5]
indicates the gas remaining cost = [3, 4, 5, 1, 2]
indicates cost ! This means:
Now, the problem asks us to find out from which station you should start so that you can travel the entire circuit and end up back at the starting station.
Let's walk through the example:
gas[3] = 4
).0 + 4 = 4
liters.cost[3] = 1
) to reach station 4.4 - 1 + 5 = 8
liters.cost[4] = 2
) to reach station 0.8 - 2 + 1 = 7
liters.cost[0] = 3
) to reach station 1.7 - 3 + 2 = 6
liters.cost[1] = 4
) to reach station 2.6 - 4 + 3 = 5
liters.cost[2] = 5
) to reach station 3.5 - 5 = 0
liters.Lets Solve !
In this approach, we attempt to start the journey from each gas station and check if we can complete the circuit.
If the car successfully completes the circuit starting from a station, return that station's index. If none of the stations work, return -1
.
#include <vector>
using namespace std;
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int n = gas.size();
// Try starting from each station
for (int start = 0; start < n; start++) {
int tank = 0; // Initialize the tank with 0 fuel
bool canComplete = true;
// Check if we can complete the circle starting from station `start`
for (int i = 0; i < n; i++) {
int current = (start + i) % n; // Current station
tank += gas[current] - cost[current]; // Update tank
// If at any point tank goes negative, we cannot continue
if (tank < 0) {
canComplete = false;
break;
}
}
// If we successfully complete the circle, return the start index
if (canComplete) {
return start;
}
}
// If no start point is found
return -1;
}
};
This approach is an optimized version of the first approach, where we minimize unnecessary checks:
If a station fails to provide enough gas to move to the next station, it means all stations between the current starting point and this station are not viable starting points. Thus, we can directly move our starting point to the next station after the failed one.
We use two pointers: front
and rear
. Initially, both start at 0, and we try to expand rear
as long as we can move from one station to the next. If we find that a move is not possible, we shift the front
to rear+1
.
#include <vector>
using namespace std;
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int n = gas.size();
int total_tank = 0, curr_tank = 0;
int start = 0;
for (int i = 0; i < n; ++i) {
total_tank += gas[i] - cost[i];
curr_tank += gas[i] - cost[i];
// If we cannot move to the next station from the current station
if (curr_tank < 0) {
start = i + 1; // Move the starting point to the next station
curr_tank = 0; // Reset the current tank
}
}
return total_tank >= 0 ? start : -1;
}
};
This approach further simplifies the problem by leveraging the idea that:
This approach is the most optimal because:
#include <vector>
using namespace std;
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int total_balance = 0; // Tracks total balance of gas over cost
int deficit = 0; // Tracks the total deficit encountered
int start = 0; // The starting index
for (int i = 0; i < gas.size(); i++) {
total_balance += gas[i] - cost[i]; // Update total balance
// If balance is negative, current start is not possible
if (total_balance < 0) {
deficit += total_balance; // Add to deficit
start = i + 1; // Move start to the next station
total_balance = 0; // Reset balance
}
}
// Check if overall balance + deficit is non-negative
return (total_balance + deficit >= 0) ? start : -1;
}
};
Approach 1 (Brute Force):
Approach 2 (Greedy with Two Pointers):
Approach 3 (Greedy with Deficit Calculation):
Share