LeetCode 134 Gas Station 题解

来源:互联网 发布:网络刷到被骗了怎么办 编辑:程序博客网 时间:2024/05/21 17:05

题意简述:有n个加油站,呈环形分布在一条公路上。给出每个加油站所能提供的油量gas,和从一个加油站到达下一个加油站消耗的油量cost。假设车的油缸可以装无限的汽油,那么能否找到一个出发点,使车能够绕公路一圈回到出发点而不会在两个加油站的中间耗尽油量。题目保证如果有解,解是唯一的。
输入:简述中的两个数组gas和cost。
输出:如果解存在,输出起始点的下标,否则输出-1。


题解:
考虑对于区间[i,j),车能否从加油站i出发,到达加油站j-1(以下省略加油站,以下标代称)。判断很简单,区间gas之和减去区间cost之和就是车到j-1时的剩余油量。

  • 如果结果是正数,说明车从i出发能够到达j-1,这时候就把终点推后,看车能不能走得更远。
  • 如果结果是负数,就说明油量不足以到达j-1,更到不了j-1以后的点。解决方法也很简单,我们把起点提前一点,以期望当前起点的前一个加油站提供的额外油量(因为要减去跑到当前起点的cost)能够抵消这部分缺的油量。

这样每一步的判断之后,区间的长度都会增加1,最后长度一定会达到n,这时候就是通过所有加油站的环路了,如果此时油量差还是负的,证明问题无解;如果油量差为正,当前的起点i就是唯一解。

对i和j的处理存在的问题是,下标在边缘位置的加减变得很混乱(0再减会变成n-1,n-1再加会变成0)。既然i大部分时候都是减,j大部分时候都是加,不妨考虑将i初始化为下标n-1,j初始化为0,因为解法不依赖于初始化起点的选择,而且这样初始化能同时解决两个问题:(1)因环路所需要的取模操作不需要了,因为i和j现在不会越过边界;(2)判断区间长度是否达到n,这样初始化的话,j == i + 1就证明刚好形成环路,因此i > j就说明应该继续进行处理。

算法的时间复杂度是O(N)(只需循环n次),空间复杂度是O(1)(只需3个int变量)。
代码实现如下:

class Solution {public:    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {        int i = gas.size() - 1;        int j = 0;        int gasLeft = gas[i] - cost[i];        // find if interval[i,j) is available        while(i > j) {            if(gasLeft < 0) {                // if gas is not enough, make the start point backward                i--;                gasLeft += gas[i] - cost[i];            } else {                // when gas is enough, make the end pointer further                gasLeft += gas[j] - cost[j];                j++;            }        }        return gasLeft >= 0 ? i : (-1);    }};
原创粉丝点击