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 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:
gas.length == n
cost.length == n
1 <= n <= 105
0 <= gas[i], cost[i] <= 104
Companies:
Amazon, IBM, tiktok, Microsoft, Goldman Sachs, Apple, ByteDance, Bloomberg, Flipkart, Hotstar
Let A[i] = gas[i] - cost[i]
. The brute force way is to try each start index and see if the prefix sums starting from this index are always >= 0
.
A better way is to loop at most twice over A
. Whenever the prefix sum drops under 0
, we simply discard this start index and use (i + 1) % N
for the next trial.
// OJ: https://leetcode.com/problems/gas-station/
// Author: github.com/lzl124631x
// Time: O(N)
// Space: O(1)
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int N = gas.size(), len = 0, start = 0;
for (int i = 0, sum = 0; i < 2 * N && len < N; ++i) {
sum += gas[i % N] - cost[i % N];
if (sum < 0) { // sum drops under 0. Discard this start index and start over.
len = sum = 0;
start = (i + 1) % N;
} else ++len;
}
return len == N ? start : -1; // If we've found a sequence of length `N` whose prefix sums are all `>= 0`, this start index is the answer.
}
};
This solution is similar to Solution 1, but it only loops through the arrays once.
The circuit can be completed if the sum of gas[i] - cost[i]
is non-negative, which is denoted using total
.
Use tank
to denote the current available gas in tank, ans
to denote the last possible answer.
When tank
is negative, this point is a dead point, which means moving from ans
to the current point is impossible.
The current point must have gas[i] - cost[i] < 0
, so we'll need to try to start from next point -- reset ans
to i + 1
, and tank
to 0
.
When we reached the end of the arrays, if total
is non-negative, ans
is the start point.
Proof:
First of all, assume the start point we found is s
. Then this algorithm guarantees we can reach point 0
from s
.
How can we prove the last part of the roundtrip -- from 0
to s
?
We use proof by contradiction to prove this works.
Assume there is a point k
(0 < k <= s
) that is unreachable in the roundtrip starting from s
.
Let D[i] = gas[i] - cost[i]
, and SUM(i, j) = D[i] + D[i+1] + ... + D[j]
.
Since total >= 0
, we have SUM(0, N-1) >= 0
, i.e.:
SUM(0, k) + SUM(k+1, s-1) + SUM(s, N-1) >= 0
Let them be a
, b
, c
respectively. We have a + b + c >= 0
.
Since we can't reach k
from s
, we have c + a <= 0
. And because c >= 0
, we have a <= 0
. Thus, this algorithm must reset the starting point when we scanned from 0
to k
. And since we reset the starting point at s-1
again, we know b <= 0
.
Given b <= 0
and a + b + c >= 0
, we have a + c >= 0
. This contradicts with c + a <= 0
. So, there is no such k
and we must be able to roundtrip from s
.
// OJ: https://leetcode.com/problems/gas-station
// Author: github.com/lzl124631x
// Time: O(N)
// Space: O(1)
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int tank = 0, total = 0, ans = 0, N = gas.size();
for (int i = 0; i < N; ++i) {
total += gas[i] - cost[i];
if ((tank += gas[i] - cost[i]) < 0) {
tank = 0;
ans = i + 1;
}
}
return total < 0 ? -1 : ans;
}
};
Let S[i] = sum(gas[0] + ... + gas[i]) - sum(cost[0] + ... + cost[i])
.
The circuit can be completed as long as sum(gas) - sum(cost) >= 0
, i.e. S[N - 1] >= 0
.
The S
array forms a polygonal line. We should use x+1
as the start index where x
is the index of the lowest point of the polygonal line.
// OJ: https://leetcode.com/problems/gas-station
// Author: github.com/lzl124631x
// Time: O(N)
// Space: O(1)
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int minVal = INT_MAX, tank = 0, ans = 0, N = gas.size();
for (int i = 0; i < N; ++i) {
tank += gas[i] - cost[i];
if (tank < minVal) {
minVal = tank;
ans = i;
}
}
return tank >= 0 ? (ans + 1) % N : -1;
}
};