Leetcode 134. 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.

解题思路:
本质上, 我们就是要找一个起点, 使得遍历一圈之后, 油量可以走完全程, 如果中间某个时刻油量小于0, 表明无法到达该站。我们可以预先计算一下从一个站i 到达 下一个站 i + 1 时候, 剩余的油量。当某处的剩余油量小于0时, 他一定不是起点, 当某处剩余油量大于0, 但是他的前面一个站的剩余油量也是大于0的时候, 表明这也不是起点, 因为,既然从上一个剩余油量大于0的站点出发都没有成功, 从这个站点出发, 初始油量更少, 就更加不可能成功了。
这里有些绕, 想明白就可以了。

下面给出代码:

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        // 计算单独一个站点 i 的油量到达 i + 1 处的剩余
        vector<int> remain(gas.size(), 0);
        for (int i = 0; i != gas.size(); i++){
            remain[i] = gas[i] - cost[i];
        }

        // 计算每段连续的正数为起点的阶段 是否可以走完全程
        for (int startid = 0; startid != gas.size(); startid++){
            // 剪枝条件: 如果当前点 < 0; 或者, 前面一个点为正数
            if (remain[startid] < 0)
                continue;

            if (startid > 0 && remain[startid - 1] >= 0)
                continue;

            int sum = 0;
            // i 表示增量
            int fixup = 0;
            for (int i = 0; i != gas.size(); i++){
                if (i + startid == gas.size())
                    fixup = gas.size();

                sum += remain[i + startid - fixup];
                if (sum < 0)
                    break;
            }
            if (sum >= 0)
                return startid;
        }

        return -1;
    }
};

网上大神们的解法:
这个方法充分抓住了解的唯一性约束条件。

/* I have thought for a long time and got two ideas: If car starts at A and can not reach B. Any station between A and B can not reach B.(B is the first station that A can not reach.) If the total number of gas is bigger than the total number of cost. There must be a solution. (Should I prove them?) */
class Solution {
public:
    int canCompleteCircuit(vector<int> &gas, vector<int> &cost) {
        int start(0),total(0),tank(0);
        //if car fails at 'start', record the next station
        for(int i=0;i<gas.size();i++) 
            if((tank=tank+gas[i]-cost[i])<0) 
                {start=i+1;total+=tank;tank=0;}
        return (total+tank<0)? -1:start;
    }
};

demo2
说下, 我对这段代码的理解
从start出发, 如果油量足够, 可以一直向后走 end++;
油量不够的时候, start向后退
最终 start == end的时候, 如果有解一定是当前 start所在位置

class Solution {
public:
    int canCompleteCircuit(vector<int> &gas, vector<int> &cost) {

       int start = gas.size()-1;
       int end = 0;
       int sum = gas[start] - cost[start];
       while (start > end) {
          if (sum >= 0) {
             sum += gas[end] - cost[end];
             ++end;
          }
          else {
             --start;
             sum += gas[start] - cost[start];
          }
       }
       return sum >= 0 ? start : -1;
    }
};

你可能感兴趣的:(LeetCode)