This is a solution for leetcode question 134. Gas Station.
Analysis
The target here is to find out if there is a starting point based on the given arrays that could let us go through all these gas stations one by one and back to the starting point in a round. And if it is, return the starting point’s index.
We can solve this question by brutal force. We can try to start at each station and check if we can pass all the stations and back to where we started. The time complexity would be where is the length of the array.
But that’s pretty slow. So how can we speed it up?
Let’s suppose that we started at station , and we arrive at station at the moment where,
The denotes the remained gas when we start from and arrive at . This means that we are not going to station because we are short of gas, and the starting point would not be .
But how about the stations between and , are they still possible to be a starting point?
Let’s say we have a station at somewhere between and , and when we arrive at from we have
which means we can go to from . As we know we can arrive at from , so we definitely can arrive at from . And it’s obvious that when we arrive at from , otherwise we won’t be able to arrive at . So plus the remained gas from to , we have
It conflicts with the given condition in , so the hypothesis would be false. There will be no station in between and can be a possible starting point. Thus we can skip all the stations in between and , and use as the new starting point and check if we can arrive at the end from there. The time complexity of this process would be .
We have reduced the time complexity from to , but this only gives a possible starting point, not a definite answer. Because we only computed if we can arrive at the end of the arrays, which is the station , but we don’t know if we can go through station to station from station with the remained gas we have.
Supposes the final candidate is station . One possible way to find out if that’s the correct answer is to continue checking if we can arrive at the station . And if we can, the answer will be , otherwise, there is no answer to meet the question’s requirements. This process’s time complexity will be , and at its worst, it will be , so the total time complexity will be .
Seems like we have a good approach here, but let’s think about this. Is it really needed to go from the beginning and check if we can go through these stations in a second round?
The answer would be no.
When we find the candidate station , we have already checked stations to , and they are not eligible. Assume that we have changed the starting point for times, and finally, we chose . So the previous starting points would be a subarray of to , and we can denote all the intervals’ end points as a vector ,
So at each interval, there is
So if the , we can not go back to , therefore there is no possible answer. And these values can be calculated as below.
So combine and ,
Turns out it is just the sum of the value of gas minus cost at each station, and it can be calculated in the first round. By now we have got the final approach, and we can write the code.
Code
def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
for i in range(len(gas)):
remained_gas += gas[i] - cost[i]
total_remained_gas += gas[i] - cost[i]
if total_remained_gas < 0: return -1
class Solution:
def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
start = 0
remained_gas = 0
total_remained_gas = 0
for i in range(len(gas)):
remained_gas += gas[i] - cost[i]
total_remained_gas += gas[i] - cost[i]
if remained_gas <= 0:
remained_gas = 0
start = i + 1
if total_remained_gas < 0: return -1
return start