【LeetCode】134. 加油站

leetcode

 

解题思路

该问题的核心是验证是否存在一个起点,使得汽车能够绕环形公路行驶一周。通过以下两个关键点可以高效解决:

  1. 油量总和验证:若总油量 sum(gas) < sum(cost),直接返回 -1(无论如何都无法绕行)。
  2. 贪心遍历:若总油量足够,则通过一次遍历找到唯一可能的起点。遍历过程中维护当前剩余油量,若剩余油量为负,说明当前起点无效,重置起点为下一加油站。

关键步骤

  1. 计算总油量差:若总油量不足以覆盖总消耗,直接返回 -1
  2. 贪心寻找起点:遍历每个加油站,累加当前剩余油量。若剩余油量为负,则从下一加油站重新开始。
  3. 唯一解验证:由于题目保证解唯一,遍历完成后若总油量足够,则最后记录的起点即为答案。

复杂度分析

  • 时间复杂度:O(n),仅需两次遍历(总油量计算 + 贪心搜索)。
  • 空间复杂度:O(1),仅用常数变量。

Golang 代码实现

func canCompleteCircuit(gas []int, cost []int) int {
    if len(gas) != len(cost) {
        return -1
    }
    totalGas := 0       // 总油量剩余
    currentGas := 0     // 当前累积油量
    start := 0          // 可能的起点索引

    for i := 0; i < len(gas); i++ {
        totalGas += gas[i] - cost[i]
        currentGas += gas[i] - cost[i]
        // 当前累积油量为负,说明起点不在当前及之前的加油站
        if currentGas < 0 {
            start = i + 1  // 重置起点为下一加油站
            currentGas = 0 // 重置当前油量
        }
    }

    // 总油量不足则无解,否则返回起点
    if totalGas >= 0 && start < len(gas) {
        return start
    }
    return -1
}

运行示例

func main() {
    // 示例1
    gas1 := []int{1, 2, 3, 4, 5}
    cost1 := []int{3, 4, 5, 1, 2}
    fmt.Println(canCompleteCircuit(gas1, cost1)) // 输出: 3

    // 示例2
    gas2 := []int{2, 3, 4}
    cost2 := []int{3, 4, 3}
    fmt.Println(canCompleteCircuit(gas2, cost2)) // 输出: -1
}

代码解析

  1. 总油量验证:通过 totalGas 累加所有加油站的净油量差(gas[i] - cost[i]),若总和为负则直接返回 -1
  2. 贪心搜索起点:遍历过程中,若当前累积油量 currentGas 为负,说明起点不在当前及之前的加油站,需重置起点为 i+1 并清空当前油量。
  3. 唯一解保证:题目保证解唯一,因此遍历完成后若总油量足够,直接返回记录的 start

应用场景

该算法适用于车辆路径规划中的加油站选择问题,例如物流运输中的节能路线优化,或自动驾驶车辆的能源调度策略。


此实现通过一次遍历即完成计算,结合总油量验证和贪心策略,确保在 O(n) 时间复杂度内找到解。

posted @ 2025-03-27 16:30  云隙之间  阅读(21)  评论(0)    收藏  举报