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,o(n):
选择gas[0]和cost[0]作为起始点,设current_gas_left表示当前剩余的汽油量,则初始current_gas_left = gas[0] - cost[0];
①如果gas[0] - cost[0] < 0,说明此站不是起点。但是数组中至少存在一点i,以i为起始,在经历0点时,current_gas_left不为负,
因此想象数组是一个圈,从0向前(n-1,n-2,...)寻找,即current_gas_left += gas[i] - cost[i],i从n-1取值,不断递减。
直到累加到current_gas_left不为负,或者i = 0,停止。
②如果gas[0] - cost[0] >= 0,或者经历了第①步,current_gas_left不为负后,继续计算后面的加油站。累加current_gas_left += gas[j] - cost[j],j从1取值,不断递增。
若累加过程中current_gas_left再次出现负值,则继续采用第①步的做法。最终当j <= i时,循环累加停止。
此时如果current_gas_left为负,说明不存在符合条件的加油站。如果不为负,则i即为满足条件的加油站起点。
代码如下:
1 class Solution { 2 public: 3 int canCompleteCircuit(vector<int> &gas, vector<int> &cost) { 4 int n = gas.size(); 5 int ind_front = n-1; 6 int ind_back = 1; 7 8 int station_cost = gas[0] - cost[0]; 9 10 if (n == 1) 11 return station_cost >= 0 ? 0 : -1; 12 13 while (ind_front >= ind_back) { 14 if (station_cost < 0) { 15 station_cost += gas[ind_front] - cost[ind_front]; 16 ind_front--; 17 continue; 18 } 19 20 if (station_cost >= 0) { 21 station_cost += gas[ind_back] - cost[ind_back]; 22 ind_back++; 23 if (ind_back == n) 24 return 0; 25 } 26 } 27 28 return station_cost >= 0 ? ind_back : -1; 29 } 30 };
解题思路2,o(n):
将所有加油站gas[i]和cost[i]想象合并成一个数组station[i],station[i]代表汽车行驶至此加油站时,将要支付的开销。
那么station[0]至station[n-1]的值,以加油站为x轴,以开销累加值作为y轴,可以在数轴上画一个折线(如下图)。不论从哪个station开始画起,折线的走势不会改变,只是在x轴上方和下方的比例会有变化。
如果只有唯一一个加油站能满足行驶一圈的话,那么一定是从折线的最低处的加油站,因为如果从那里作为起点,不管折线走势如何下降,current_gas_left总能保持大于等于0;
如何从任意一点找到曲线走势的最低点?只需要从任一加油站开始累加其开销值(gas[i] - cost[i]),记录累加的最小值,出现最小值的点就是曲线走势的最低点;
如果最终all gases > all costs,则加油站起始点就在出现最小值的下一个加油站。
代码:
1 class Solution { 2 public: 3 int canCompleteCircuit(vector<int> &gas, vector<int> &cost) { 4 int current_gas_left = 0; 5 int lowest_station = -1; 6 int min = 0; 7 8 for (int i = 0; i < gas.size(); ++i) { 9 current_gas_left += gas[i] - cost[i]; 10 if (current_gas_left < min) { 11 min = current_gas_left; 12 lowest_station = i; 13 } 14 } 15 16 if (current_gas_left >= 0) 17 return lowest_station + 1; 18 else 19 return -1; 20 } 21 };