返回

Python 巧解 leetcode 134. Gas Station 燃油补给问题,告别超时,O(n)算法轻松过关

后端

问题背景

有一个环形公路,沿途分布着 n 个加油站,每个加油站都有一定的燃油供应量。现在有一辆车要沿着环形公路行驶一圈,但它目前没有足够的燃油。为了完成整个旅程,这辆车需要在某些加油站补充燃油。

已知:

  • 环形公路上的加油站数量 n,及每个加油站的燃油供应量 gas[i]。
  • 汽车的油箱容量为 capacity,初始油量为 0。
  • 汽车每次只能在加油站补充燃油,且每次补充燃油后油箱的油量不会超过 capacity。
  • 汽车可以多次经过同一个加油站。

目标:

  • 找到一个最优的加油站,使得汽车能够沿着环形公路行驶一圈。

暴力解法

乍一看,解决这个问题的方法很简单:从第一个加油站出发,逐个加油站地检查,看看是否能够到达下一个加油站。如果能够到达下一个加油站,则继续前进;如果无法到达,则返回第一个加油站并从下一个加油站开始检查。

这种方法被称为暴力解法。它简单易懂,但效率极低。对于 n 个加油站,暴力解法的时间复杂度为 O(n^2)。当 n 较大时,这种方法会超时。

巧妙的 O(n) 算法

为了提高效率,我们需要找到一种巧妙的算法来解决这个问题。一种方法是使用贪心算法。贪心算法是一种在每一步做出局部最优选择,希望借此得到全局最优解的算法。

在我们的问题中,我们可以使用贪心算法来选择最优的加油站。具体步骤如下:

  1. 计算总油量和总消耗油量。总油量是所有加油站的燃油供应量之和,总消耗油量是汽车环绕一圈所需的燃油量。
  2. 如果总油量小于总消耗油量,则无法完成旅程,直接返回 -1。
  3. 否则,从第一个加油站出发,逐个加油站地检查,看看是否能够到达下一个加油站。
  4. 如果能够到达下一个加油站,则继续前进;如果无法到达,则将当前加油站的燃油供应量添加到汽车油箱中,然后从下一个加油站开始检查。
  5. 重复步骤 3 和步骤 4,直到汽车回到第一个加油站。
  6. 如果汽车能够回到第一个加油站,则找到最优的加油站。

这种算法的时间复杂度为 O(n),因为我们只需要遍历一次环形公路上的加油站。

代码实现

def canCompleteCircuit(gas, cost):
    """
    :type gas: List[int]
    :type cost: List[int]
    :rtype: int
    """
    total_gas = sum(gas)
    total_cost = sum(cost)

    if total_gas < total_cost:
        return -1

    start_station = 0
    current_gas = 0

    for i in range(len(gas)):
        current_gas += gas[i] - cost[i]
        if current_gas < 0:
            start_station = i + 1
            current_gas = 0

    return start_station

结论

在这篇文章中,我们介绍了 leetcode 134. Gas Station 这道经典算法题的 Python 解法。我们首先介绍了一种暴力的解法,然后分析其局限性,最后给出一种巧妙的 O(n) 算法,轻松过关!