zl程序教程

您现在的位置是:首页 >  后端

当前栏目

【Leetcode刷题Python】134. 加油站

PythonLeetCode 刷题 加油站
2023-09-14 09:12:59 时间

1 题目

在一条环路上有 n 个加油站,其中第 i 个加油站有汽油 gas[i] 升。

你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。

给定两个整数数组 gas 和 cost ,如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1 。如果存在解,则 保证 它是 唯一 的。

输入: gas = [1,2,3,4,5], cost = [3,4,5,1,2]
输出: 3
解释:
从 3 号加油站(索引为 3 处)出发,可获得 4 升汽油。此时油箱有 = 0 + 4 = 4 升汽油
开往 4 号加油站,此时油箱有 4 - 1 + 5 = 8 升汽油
开往 0 号加油站,此时油箱有 8 - 2 + 1 = 7 升汽油
开往 1 号加油站,此时油箱有 7 - 3 + 2 = 6 升汽油
开往 2 号加油站,此时油箱有 6 - 4 + 3 = 5 升汽油
开往 3 号加油站,你需要消耗 5 升汽油,正好足够你返回到 3 号加油站。
因此,3 可为起始索引。

2 解析

(1)思路
考虑从第 0 个点出发,能否回到第 0 个点。

考虑从第 1 个点出发,能否回到第 1 个点。

考虑从第 2 个点出发,能否回到第 2 个点。

… …

考虑从第 n 个点出发,能否回到第 n 个点。
但这样的时间复杂度较高,因为有一个测试例子是,会超过时间限制。

输入:
[0,0,0,0,0,0,0,0,0,0,0,0,0,0…0,2]
[0,0,0,0,0,0,0,0,0,0,0,0,0,0…1,0]
输出:99999

我们考虑一下下边的情况进行优化

* * * * * *
^     ^
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 即可。

3 Python 实现

class Solution:
    def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
            n = len(gas)
            i = 0
            while i < n:
                j = i
                remain = gas[i]
                while remain>=cost[j]:
                    remain = remain -cost[j]+gas[(j+1)%n]
                    j = (j+1)%n
                    if j==i:
                        return i
                if j<i:
                    return -1
                elif j==i:
                    i+=1
                else:
                    i = j
            return -1