Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[LeetCode] 134. Gas Station #134

Open
grandyang opened this issue May 30, 2019 · 3 comments
Open

[LeetCode] 134. Gas Station #134

grandyang opened this issue May 30, 2019 · 3 comments

Comments

@grandyang
Copy link
Owner

grandyang commented May 30, 2019

 

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.

 

这道转圈加油问题不算很难,只要想通其中的原理就很简单。我们首先要知道能走完整个环的前提是gas的总量要大于cost的总量,这样才会有起点的存在。假设开始设置起点start = 0, 并从这里出发,如果当前的gas值大于cost值,就可以继续前进,此时到下一个站点,剩余的gas加上当前的gas再减去cost,看是否大于0,若大于0,则继续前进。当到达某一站点时,若这个值小于0了,则说明从起点到这个点中间的任何一个点都不能作为起点,则把起点设为下一个点,继续遍历。当遍历完整个环时,当前保存的起点即为所求。代码如下:

 

解法一:

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

 

我们也可以从后往前遍历,用一个变量mx来记录出现过的剩余油量的最大值,total记录当前剩余油量的值,start还是记录起点的位置。当total大于mx的时候,说明当前位置可以作为起点,更新start,并且更新mx。为啥呢?因为我们每次total加上的都是当前位置的油量减去消耗,如果这个差值大于0的话,说明当前位置可以当作起点,因为从当前位置到末尾都不会出现油量不够的情况,而一旦差值小于0的话,说明当前位置如果是起点的话,油量就不够,无法走完全程,所以我们不更新起点位置start。最后结束后我们还是看totoa是否大于等于0,如果其小于0的话,说明没有任何一个起点能走完全程,因为总油量都不够,参见代码如下:

 

解法二:

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        int total = 0, mx = -1, start = 0;
        for (int i = gas.size() - 1; i >= 0; --i) {
            total += gas[i] - cost[i];
            if (total > mx) {
                start = i;
                mx = total;
            }
        }
        return (total < 0) ? -1 : start;
    }
};

 

类似题目:

Reaching Points

Transform to Chessboard

Cheapest Flights Within K Stops

 

参考资料:

https://leetcode.com/problems/gas-station/discuss/42568/Share-some-of-my-ideas.

https://leetcode.com/problems/gas-station/discuss/42656/8ms-simple-O(n)-c++-solution

 

LeetCode All in One 题目讲解汇总(持续更新中...)

@miayu79
Copy link

miayu79 commented Jan 5, 2020

想请教为什么 若这个值小于0了,则说明从起点到这个点中间的任何一个点都不能作为起点?

@BoYaoEssex
Copy link

想请教为什么 若这个值小于0了,则说明从起点到这个点中间的任何一个点都不能作为起点?

同问

@CrazyGuo
Copy link

我们考虑一下下边的情况。


^ ^
i j
当考虑 i 能到达的最远的时候,假设是 j。

那么 i + 1 到 j 之间的节点是不是就都不可能绕一圈了?

假设 i + 1 的节点能绕一圈,那么就意味着从 i + 1 开始一定能到达 j + 1。

又因为从 i 能到达 i + 1,所以从 i 也能到达 j + 1。

但事实上,i 最远到达 j 。产生矛盾,所以 i + 1 的节点一定不能绕一圈。同理,其他的也是一样的证明。

所以下一次的 i 我们不需要从 i + 1 开始考虑,直接从 j + 1 开始考虑即可。

还有一种情况,就是因为到达末尾的时候,会回到 0。

如果对于下边的情况。


^ ^
j i
如果 i 最远能够到达 j ,根据上边的结论 i + 1 到 j 之间的节点都不可能绕一圈了。想象成一个圆,所以 i 后边的节点就都不需要考虑了,直接返回 -1 即可。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants