首页 > 代码库 > leetcode Gas Station

leetcode Gas Station

gas[i]表示第i个站点可以加的油,cost[i]表示到下一个站点要消耗的油,一开始油箱空,假设油箱可以装无限的油。然后在一个环中。那个起点开始可以绕一圈回到原点,有且仅有一个答案。如果没有则返回-1.

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.

思路一,一开始很简单的想到就是遍历一下每个节点看看能不能走一圈就行。然后需要的剪枝是,如果该起点的cost比gas大,那就不用试了,肯定不行,还有就是如果gas-cost的累加和小于0了也是不要再继续试了。

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

每个节点都考虑必然超时啊。然后我们稍微改进一下就行了。

我们用left数组存每个节点剩余的油,也就是gas[i]-cost[i],可能是负数,那么我们从0开始,如果left[i]的累加一直都大于等于0循环回到原点,那就是有解。如果累加到某个小标小于0了,那么我们不是从i+1继续判断累加值,而是从累加到的那个点的下一个点开始继续判断,因为之前的累加和已经不可能走完了,所有起点不会再前面。这样的话,我们要判断的是,一旦有绕过最后一个点又从头开始的时候,那么要么就找到了节点,要么就是没有符合的点,也就是终止条件之一了。例如我们的left数组为:

-2, 2, -2, -1, 4, 6,

然后6又循环到-2.

那么我们一开始sum是-2,那么i+1判断2大于等于0,符合,然后2+ -2 等于0还是符合,然后-1不符合了,然后4符合,4+6=10符合,然后绕到-2,变成8还是大于等于零继续,加2变10,然后-2, -1 最后回到4的时候是大于零的。所以我们刚才从4开始就是符合回来的,那么4的下标就是要返回的答案。当然我的例子举得不是很对,因为不止一个答案,6开始也可以。但题目说只有一个答案的思路和上面说的是一样的。这样就只是O(n)的时间了。

这是一开始试着写的比较挫的代码:

class Solution {public:    int canCompleteCircuit(vector<int> &gas, vector<int> &cost)    {        vector<int> left(gas);        for (int i = 0; i < left.size(); ++i)            left[i] = gas[i] - cost[i];        for (int i = 0; i < left.size(); )        {            int sum = 0, cnt = -1, in = i;            bool flag = false;            while(sum >= 0)            {                sum += left[in];                in++;                if (in >= left.size()) flag = true;                in = in % left.size();                cnt++;                if (cnt == left.size())                    return i;            }            if (flag) return -1;            i = in;        }        //return -1;    }};
View Code

然后改的比较好看一点,变量少了一些如下:

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

 

leetcode Gas Station