问题描述:
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.
代码一:
1 class Solution { 2 public: 3 int canCompleteCircuit(vector<int> &gas, vector<int> &cost) { //时间复杂度为O(n) 4 int total=0; 5 unsigned i,j,start; 6 for(i=0; i<gas.size(); ) 7 { 8 start = i; 9 int residual = gas[i]-cost[i]; 10 total += gas[i]-cost[i]; 11 12 for(j =i+1; j<gas.size(); j++) 13 { 14 if(residual<0) 15 { 16 i=j; 17 break; 18 } 19 total += gas[j]-cost[j]; 20 residual += gas[j]-cost[j]; 21 } 22 i=j; 23 } 24 return total>=0? start : -1; 25 } 26 };
代码二:
1 class Solution { 2 public: 3 int canCompleteCircuit(vector<int> &gas, vector<int> &cost) { 4 unsigned start = 0; 5 int current_gas = 0; 6 int total_gas = 0; 7 for(unsigned i=0; i<gas.size(); i++) 8 { 9 current_gas += gas[i]-cost[i]; 10 total_gas += gas[i]-cost[i]; 11 if(current_gas<0) //从第i站出发到第i+1站很耗油 12 { 13 start = i+1; 14 current_gas = 0; 15 } 16 } 17 return total_gas>=0 ? start : -1; 18 } 19 };
代码一和代码二的思想是一样的,只是形式不太一样,相比较而言,代码二可读性更好。
问题分析:
如果sum(gas)>=sum(cost),则一定存在一个合适的站点,使得从该站点出发汽车可以转一圈再返回到起始点,但是起始点的唯一性并不能保障。
比如gas=[4,5,6,7],cost=[1,2,3,4],则任一站点都可以作为起始点。
所以本题中给出Note:
The solution is guaranteed to be unique.
如果sum(gas)<sum(cost),则不存在这样的起始点,这一点很容易想到。
代码思想:
假设有n个站点:S1,S2,S3,...,Sn,当前油箱内油量为0,从S1开始,判断从S1站点能否开到S2站点,如果可以的话说明达到S2站点时汽车内油量>=0,
我们标记S1>0,表示从S1可以到达S2;否则,标记S1<0。 当Si>0时,继续判断Si+1是否大于0,当Si<0时,说明当前设置的起始点不成功,将新的起始点
设为Si+1,判断从Si+1->Si+2->...->Sn是否成功。 如果从Si+1能否到达Sn,并且sum(gas)>=sum(cost),那么Si+1就可以作为起始点。
举个例子: S1, S2, S3, S4, S5, S6, S7,..., Si, Si+1, Si+2,..., Sn 标记为绿色的表示在遍历过程中被设为起始点的站点
current_gas |>0 >0 <0 | >0 >0 >0 >0,...,<0 | >0 >0 ,..., >0|
| <0 | <0 | >0 |
sum(gas13)-sum(cost13)<0