在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i]升。你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第i+1个加油站需要消耗汽油 cost[i]升。你从其中的一个加油站出发,开始时油箱为空。如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1。
说明:
- 如果题目有解,该答案即为唯一答案。 输入数组均为非空数组,且长度相同。
- 输入数组中的元素均为非负数。
示例 1:
输入:
gas = [1,2,3,4,5]
cost = [3,4,5,1,2]
输出: 3
解释:
从 3 号加油站(索引为 3 处)出发,可获得 4 升汽油。此时油箱有 = 0 + 4 = 4 升汽油
开往 4 号加油站,此时油箱有 4 - 1 + 5 = 8 升汽油
开往 0 号加油站,此时油箱有 8 - 2 + 1 = 7 升汽油
开往 1 号加油站,此时油箱有 7 - 3 + 2 = 6 升汽油
开往 2 号加油站,此时油箱有 6 - 4 + 3 = 5 升汽油
开往 3 号加油站,你需要消耗 5 升汽油,正好足够你返回到 3 号加油站。
因此,3 可为起始索引。
示例 2:
输入:
gas = [2,3,4]
cost = [3,4,3]
输出: -1
解释:
你不能从 0 号或 1 号加油站出发,因为没有足够的汽油可以让你行驶到下一个加油站。
我们从 2 号加油站出发,可以获得 4 升汽油。 此时油箱有 = 0 + 4 = 4 升汽油
开往 0 号加油站,此时油箱有 4 - 3 + 2 = 3 升汽油
开往 1 号加油站,此时油箱有 3 - 3 + 3 = 3 升汽油
你无法返回 2 号加油站,因为返程需要消耗 4 升汽油,但是你的油箱只有 3 升汽油。
因此,无论怎样,你都不可能绕环路行驶一周。
题目给定两个数组gas和cost分别表示第i个加油站可以补充的油量,以及第i个加油站到下一个加油站所耗费的油量。例如,示例1中设置gas = [1,2,3,4,5],cost = [3,4,5,1,2],题目要求绕环路行驶一周,那么这些加油站可以组成一个环。假设从i个加油站出发,到达下一个加油站剩下的油量total = total + gas[i] - cost[i]:
-
如果此时
total已经小于0,并且还没有走完一圈,那么继续考虑下一个起点 -
如果
total >= 0并且已经绕了一圈,那么直接返回此时的起点即可答案唯一
-
如果判断了所有的起点仍无法实现绕圈一周,那么返回
-1
整体的判断思路如下所示:
如上所示,如果从第3个加油站出发,绕一圈回到起点时剩余的油量正好为0,表示可以成功绕环路行驶一周。
Python解题代码如下,为了方便记录出发点和遍历所有可能的起来,这里使用了list的拼接来保证每次都可以使用遍历索引0 ~ l - 1来表示绕圈一次。
class Solution:
def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
if not gas or not cost:
return -1
l = len(gas)
flag = -1
for i in range(l):
g = gas[i:] + gas[:i]
c = cost[i:] + cost[:i]
total = 0
for j in range(l):
total = total + g[j] - c[j]
if total < 0: break
if total >= 0 and j == l - 1:
flag = i
break
if flag != -1:return flag
return flag
这样的方式时间复杂度为 O ( N 2 ) O(N^2) O(N2),空间复杂度为 O ( N ) O(N) O(N)。
由于Java中数组的分片和拼接操作比较麻烦,这里首先给出Python的解题代码。
更优的解法就是官方题解给出的解法,基本思想也很简单。遍历所有的加油站,使用total += gas[i] - cost[i]记录走完所有的加油站耗的总油量,可能有正有负;使用cur += gas[i] - cost[i]记录到某一站还有多少油。如果最后total >= 0,那么必然可以从某一站出发绕圈一周,至于哪一站是合法的出发点,需要看cur的值。
为了记录可能的出发点,使用变量station记录出发点,如果到某一站时cur < 0,那么station更新为i + 1,同时将cur置0,继续往后判断。如果最后total >= 0,那么station表示的就是合法的出发点。
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
if(gas == null || cost == null){
return -1;
}
int total = 0;
int cur = 0;
int station = 0;
for(int i = 0; i < gas.length; i++){
total += gas[i] - cost[i];
cur += gas[i] - cost[i];
if(cur < 0){
station = i + 1;
cur = 0;
}
}
return total >= 0 ? station : -1;
}
}