题意
有n个加油站围成环,i点有gas[i]升汽油,i点开到i + 1点需要cost[i]升汽油,求是否有一个点,从这点开始可以绕n个点一周。注意,过程中汽油储备不可以为负。
思路
设现在的开始点为l,下一个要到的点为r,如果现在汽油储备为非负,就能继续往前走,否则将开始点往后移。
为什么是将开始点往后移,即,为什么区间[l, r]中的任意一个点都不能作为开始点?
对于一段区间[l, r],对于任意[l, j](l <= j < r),区间的汽油储备一定是正的,否则也不会走到r点。如果将开始点往前移,一定会减少汽油储备。通俗地说,将开始点往后移是为了增加汽油储备。
代码1
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int n = gas.size();
gas.insert(gas.end(), gas.begin(), gas.end());
cost.insert(cost.end(), cost.begin(), cost.end());
int l = n - 1, r = n;
int sum = gas[l] - cost[l];
int ans = -1;
while(r - l < n){
if(sum >= 0){
sum += gas[r] - cost[r];
r++;
}
else{
l--;
sum += gas[l] - cost[l];
}
}
if(sum < 0) return -1;
else return l;
}
还有一种对环的巧妙处理,可以学习一下,将r设置为0,l设置为size - 1,在r++、l--的过程中就形成了一个环。
代码2
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int l = gas.size() - 1, r = 0;
int Gas = gas[l] - cost[l];
while(l > r){
if(Gas >= 0){
Gas += gas[r] - cost[r];
r++;
}
else{
l--;
Gas += gas[l] - cost[l];
}
}
if(Gas >= 0) return l;
else return -1;
}