【Leetcode】【Medium】Gas Station

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 };
原文地址:https://www.cnblogs.com/huxiao-tee/p/4227440.html