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;
    }
};
原文地址:https://www.cnblogs.com/higerzhang/p/4156646.html