在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。
你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。
如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1。
说明:
示例 1: 输入:
输出: 3 解释:
示例 2: 输入:
直接两遍for循环,以每一个节点为起点进行遍历,如果能够到达起点则可以开一圈。但是这种方法太暴力,已经会报超出时间限制,所以此处不建议这个方法!
如果遍历下来,总的油量是大于0的话,则最后是一定能够遍历一圈的。说明 各个站点的加油站 剩油量rest[i]相加一定是大于等于零的。
每个加油站的剩余量rest[i]为gas[i] - cost[i]。
i从0开始累加rest[i],和记为curSum,一旦curSum小于零,说明[0, i]区间都不能作为起始位置,因为这个区间选择任何一个位置作为起点,到i这里都会断油,那么起始位置从i+1算起,再从0计算curSum。
数组下标 | 0 | 1 | 2 | 3 | 4 |
---|---|---|---|---|---|
gas | 1 | 2 | 3 | 4 | 5 |
cost | 3 | 4 | 5 | 1 | 2 |
rest_gas | -2 | -2 | -2 | 3 | 3 |
这里可以看出起点就是3这个 位置
疑问:
如果出现更大的负数,就是更新i,那么起始位置又变成新的i+1了。
如果区间中有一个点n开始大于0的话,那么(n,i)的值一定是大于0的,而总的是要小于0的,所以前面(0,n)的值一定是小于0的,所以这个时候起点早就已经变更了。
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int len = gas.length;
int curSum = 0; // 当前的和
int totalSum = 0; // 当前的总和
int start = 0; // 起点
for (int i = 0; i < len; i++) {
curSum += gas[i] - cost[i];
totalSum += gas[i] - cost[i];
if (curSum < 0) {
start = i+1;
curSum = 0;
}
}
if (totalSum < 0) return -1;
return start;
}
}