Loading

【leetcode】134. Gas Station

There are n gas stations along a circular route, where the amount of gas at the ith station is gas[i].

You have a car with an unlimited gas tank and it costs cost[i] of gas to travel from the ith station to its next (i + 1)th station. You begin the journey with an empty tank at one of the gas stations.

Given two integer arrays gas and cost, return the starting gas station's index if you can travel around the circuit once in the clockwise direction, otherwise return -1. If there exists a solution, it is guaranteed to be unique

Example 1:

Input: gas = [1,2,3,4,5], cost = [3,4,5,1,2]
Output: 3
Explanation:
Start at station 3 (index 3) and fill up with 4 unit of gas. Your tank = 0 + 4 = 4
Travel to station 4. Your tank = 4 - 1 + 5 = 8
Travel to station 0. Your tank = 8 - 2 + 1 = 7
Travel to station 1. Your tank = 7 - 3 + 2 = 6
Travel to station 2. Your tank = 6 - 4 + 3 = 5
Travel to station 3. The cost is 5. Your gas is just enough to travel back to station 3.
Therefore, return 3 as the starting index.

Example 2:

Input: gas = [2,3,4], cost = [3,4,3]
Output: -1
Explanation:
You can't start at station 0 or 1, as there is not enough gas to travel to the next station.
Let's start at station 2 and fill up with 4 unit of gas. Your tank = 0 + 4 = 4
Travel to station 0. Your tank = 4 - 3 + 2 = 3
Travel to station 1. Your tank = 3 - 3 + 3 = 3
You cannot travel back to station 2, as it requires 4 unit of gas but you only have 3.
Therefore, you can't travel around the circuit once no matter where you start.

Constraints:

  • gas.length == n
  • cost.length == n
  • 1 <= n <= 105
  • 0 <= gas[i], cost[i] <= 104

 这道题需要求一个起始的站点k,从而保证从k站点开始,能够循环一圈的遍历所有station。这里有两点很直接的point:

1、如果当前station的 cost>gas那么铁定不能将该站点作为起始站点。

2、如果所有站点都能遍历一遍,那么gas的累加和一定是大于等于cost的累加和。

 对于这道题我首先想到了一个简单的方法,循环遍历数组,让每一个站点k作为起始站点试一遍,然后判断能否跑到下一个站点,如果全部遍历一遍都可以则输出k,否则选择下一个站点k+1作为起始,重复操作。很明显这样有两层循环,时间复杂度为o(n^2),直觉告诉我铁定不能oc。。。。

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        // 暴力发就是每个gas station 进行检索一次
        int n=gas.size();
        int len=2*n-1;
        int index=0;
        int flag=1;
        while(index<n){
            int res=0;
            flag=1;
            for(int i=index;i<=len;++i){
                res=res-cost[i%n]+gas[i%n];
                if(res<0) {
                    flag=0;
                    break;
                }
            }
            if(flag) break;
            index++;
        }
        return flag==1? index:-1;
    }
};

   倒在最后一个超长的test了。

  那么如何优化呢,o(n^2)的复杂度指定不行的。后面看了大佬的代码才恍然大悟。

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        // 暴力发就是每个gas station 进行检索一次
        int tot_gas=0,cur_gas=0,k=0;
        for(int i=0;i<gas.size();++i){
            tot_gas+=gas[i]-cost[i];
            cur_gas+=gas[i]-cost[i];
            if(cur_gas<0){
                cur_gas=0;
                k=i+1; //这行代码很关键
            }
        }
        return tot_gas>=0? k:-1;
        
    }
};

    这里维护 tank 总的 tot_gas,以及当前 tankcur_gas,更新方式基本相同  tot_gas+=gas[i]-cost[i];,但注意一点,当 cur_gas<0 时表明汽车无法到达该station,同时也表明从上一个起点 k 到当前的  station i 之间的任何 station 都无法作为起点进行循环,下一个起点得是  k=i+1(very important)。

   为啥呢,假设从 起点 k=0 开始,当从  station i-1=》station icur_gas[i]<0 , 可以证明从  station  0~i, 这些结点都无法作为起点。我的思考如下:

1. cur_gas[i]<0 ,可以得到 对于当前  station i :cost[i]>gas[i],station i  无法作为起点。

2.假设能从 station 0station i-1,可以得到从 station 0作为起始的cur_gas[i-1] 一定是大于以station i-1 作为起始的cur_gas[i-1], 因为前面能到达的话,会累加很多之前正的cur_gas,这样就可以证明,如果从station 0都无法到达station i=》从 station i-1 也无法到达 station i 所以无论以 0~i 哪个station 作为起点,计算得到的cur_gas[i] 都必将为为负值

3.则下一个起点必然是station i+1

4.最后判断一下tot_gas, 如果能够循环检索,必然总的tot_gas为正值。

该代码直接复杂度直接为o(n),贼牛逼。

posted @ 2022-01-22 01:06  aalanwyr  阅读(138)  评论(0编辑  收藏  举报