题目:
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, otherwise return -1.
Note:
The solution is guaranteed to be unique.
思路:这道题乍看不是很难,最开始想到的办法就是一个点一个点计算,计算到没油了,证明这个点不能做出发点,移动到下一个点出发,继续重复计算。这个思路简答,但是编译超时。而且还需要处理环的问题。
LTE Code:
class Solution { public: int canCompleteCircuit(vector<int> &gas, vector<int> &cost) { if(gas.size() == 0) return -1; int len = gas.size(); for(int i = 0; i < len; i++) { int gascapcity = gas[i] - cost[i]; int j = (i+1) % len; while(gascapcity >= 0) { if(j == i) return i; gascapcity = gascapcity + gas[j] - cost[j]; j = (j+1) % len; } } return -1; } };
Answer 1:
思路:为了解决环的问题,我们将出发点start设在数组末尾,结束点end设为数组头,在start 未和end相遇前,我们进行操作,如果油的总和一直大于等于0,我们移动end++,如果小于0,我们移动start--, 并且加上此时的剩余量gas[newstart] - cost[newstart],需要注意的是,我们是在之前统计的sum基础上相加(即加上newstart 到end之间的累积量)。因为之后的求和我们是从end之后开始计算的,这段的累积量不能忘记,
之后我们不会重复计算。如果最后开始点和终止点相遇时,sum >= 0返回start, 如果小于0,说明我们不能完成任务,返回-1.
AC Code:
class Solution { public: int canCompleteCircuit(vector<int> &gas, vector<int> &cost) { int start = gas.size() - 1; int end = 0; int sum = gas[start] - cost[start]; while(start > end) { if(sum >= 0) { sum += gas[end] - cost[end]; end++; } else { start--; sum += gas[start] - cost[start]; //需要加上newstart到end之间的累积量,因为end是从数组头开始计算的,符号是+= 即sum = sum + gas[start]-cost[start]; } } return sum >= 0 ? start : -1; } };
Answer 2:
思路:我们总结出以下两个属性:相关的证明可以看:LeetCode Gas Station
1.如果总的gas - cost小于零的话,那么无解返回-1
2.如果前面所有的gas - cost加起来小于0,那么前面所有的点都不能作为出发点。
因此我们只需要遍历一次,维护三个变量,start表示起点,如果一旦不满足从该起点到此处所有点都不能作为出发点,tank表示从新起点开始,统计的油的积累量,total表示从0开始到最后统计的起点前,欠缺的油的量。如果total + tank >=0, 说明任务能完成,否则不行。
AC Code:
class Solution { public: int canCompleteCircuit(vector<int> &gas, vector<int> &cost) { int start = 0; int total = 0; int tank = 0; for(int i = 0; i < gas.size(); i++) { if((tank += gas[i] - cost[i]) < 0) { start = i + 1; total += tank; tank = 0; } } return (total + tank >= 0) ? start : -1; } };
这种题目,还是比较考查我们处理问题的能力。规律可能很难快速发现,最好的办法,就是先举些例子,观察他们的特性,然后总结出来,再设计合适的算法。