Week12 Gas Station

Week12

Greedy
question source: Gas Station

question description

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 in the clockwise direction, otherwise return -1.

Note:

If there exists a solution, it is guaranteed to be unique.
Both input arrays are non-empty and have the same length.
Each element in the input arrays is a non-negative integer.
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.

解决方法

这道题的标签是Greedy。是说有一定数量的站,每到一个站能获得一定数量的汽油,去下一站会消耗不同数量的汽油,问能否从某一个点出发,按顺序访问完所有站一圈,如果能,则返回开头的点,如果不能,则返回-1。
老规矩,直接暴力解法。从第1个点开始模拟这个 过程,如果不能进行下去,则从下一个点开始,题干说了,这个解是唯一的,如果找到有一个点开始,能访问所有的点,则直接返回这个点。

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        int size = cost.size();
        for(int i = 0; i < size; i++){
            int volumn = gas[i];
            int j = 0;
            while(j != size){
                volumn -= cost[(i + j) % size];
                if(volumn < 0)
                    break;
                j++;
                volumn += gas[(i + j) % size];
            }
            if(volumn >= 0) return i;
        }
        return -1;
    }    
};

这里没有涉及任何关于贪心的思想,只是单纯地模拟它的过程,过了。算法时间复杂度是 O ( n 2 ) O(n^2)
现在再思考如何利用贪心算法,在哪一步使用贪心。一个简单的思想就是,我们争取去一个站,都是净获得汽油的,就是得到的汽油比消耗的汽油要多。积累起来的汽油越多越好。于是算法就来了,先计算去每一站可以积累多少汽油,然后从第0个开始遍历,计算开始节点,开始为0,每到一个点计算累积的量,开妈的累积量为0,如果累积量小于0,则说明开始的点不可能为前面的所有节点,只能是后面的节点,因此更新开始的点为后面的第1个节点,同时重置累积量为0。
这里运用了一个事实,如果总的积累量不为0,那么此题必定存在解,也就是肯定能找到一个方案使得汽车能依次遍历所有站点一遍

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        int size = cost.size();
        int gain[size];
        int sum = 0;
        for(int i = 0; i < size; i++){
            gain[i] = gas[i] - cost[i];
            sum += gain[i];
        }
        if(sum < 0) return -1;
      
        int begin = 0;
        int max = 0;
        for(int i = 0; i < size; i++){
            max += gain[i];
            if(max < 0){
                max = 0;
                begin = i + 1;
            }          
        }
        return begin;        
    }    
};

算法复杂度是 O ( n ) O(n)

猜你喜欢

转载自blog.csdn.net/pjsfirstlaw/article/details/84404880