There are N gas stations along a circular route, where the amount of gas at station i is gas[i].
You have a car with an unlimited gas tank and it costs cost[i] of gas to travel from station i to its next station (i+1). You begin the journey with an empty tank at one of the gas stations.
Return the starting gas station’s index if you can travel around the circuit once in the clockwise direction, otherwise return -1.
Note:
If there exists a solution, it is guaranteed to be unique.
Both input arrays are non-empty and have the same length.
Each element in the input arrays is a non-negative integer.
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.
方法1: 暴力解
思路:
从每一个点尝试出发,如果中间被打断,则break。如果没有找到解,return -1。
易错点
- 题目中是先在 i 点加油,如果remain >= cost[i] ,才能走到i + 1点继续加油
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int n = gas.size();
for (int start = 0; start < n; start++){
int count = n;
int remain = gas[start];
for (int i = start; count > 0; i++){
if (remain >= cost[i % n]){
remain -= cost[i % n];
remain += gas[(i + 1) % n];
count --;
}
else break;
}
if (count == 0) return start;
}
return -1;
}
};
方法2:
思路:
参考这个同学的方法:https://www.cnblogs.com/boring09/p/4248482.html
grandyang:http://www.cnblogs.com/grandyang/p/4266812.html
两个重要事实:
- 如果全程累计是非负和,一定存在一个位置可以作为start而走完全程
- 假如从位置i开始,i+1,i+2…,一路开过来一路油箱都没有空。说明什么?说明从i到i+1,i+2,…肯定是正积累。 现在突然发现开往位置j时油箱空了。这说明什么?说明从位置i开始没法走完全程(废话)。那么,我们要从位置i+1开始重新尝试吗?不需要!为什么?因为前面已经知道,位置i肯定是正积累,那么,如果从位置i+1开始走更加没法走完全程了,因为没有位置i的正积累了。同理,也不用从i+2,i+3,…开始尝试。所以我们可以放心地从位置j+1开始尝试。
每次跳到 j + 1 的时候,更新一个sum,但是保留一个之前没能走完的路上欠下的债。total += gas[i] - cost[i],最后在判断一下是否全程累计为负。如果走通了,说明路上没有一个站点是负油量,只要最后一站没有耗尽,就可以返回最后一次更新的start。而反过来如果全程油量是负,说明最后这一下也没有走通,并且后面任何start也不可能走通,返回 -1。
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int total = 0, sum = 0, start = 0;
for (int i = 0; i < gas.size(); ++i) {
total += gas[i] - cost[i];
sum += gas[i] - cost[i];
if (sum < 0) {
start = i + 1;
sum = 0;
}
}
return (total < 0) ? -1 : start;
}
};