【LeetCode】134. 加油站
解题思路
该问题的核心是验证是否存在一个起点,使得汽车能够绕环形公路行驶一周。通过以下两个关键点可以高效解决:
- 油量总和验证:若总油量
sum(gas) < sum(cost),直接返回-1(无论如何都无法绕行)。 - 贪心遍历:若总油量足够,则通过一次遍历找到唯一可能的起点。遍历过程中维护当前剩余油量,若剩余油量为负,说明当前起点无效,重置起点为下一加油站。
关键步骤
- 计算总油量差:若总油量不足以覆盖总消耗,直接返回
-1。 - 贪心寻找起点:遍历每个加油站,累加当前剩余油量。若剩余油量为负,则从下一加油站重新开始。
- 唯一解验证:由于题目保证解唯一,遍历完成后若总油量足够,则最后记录的起点即为答案。
复杂度分析
- 时间复杂度: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 }
代码解析
- 总油量验证:通过
totalGas累加所有加油站的净油量差(gas[i] - cost[i]),若总和为负则直接返回-1。 - 贪心搜索起点:遍历过程中,若当前累积油量
currentGas为负,说明起点不在当前及之前的加油站,需重置起点为i+1并清空当前油量。 - 唯一解保证:题目保证解唯一,因此遍历完成后若总油量足够,直接返回记录的
start。
应用场景
该算法适用于车辆路径规划中的加油站选择问题,例如物流运输中的节能路线优化,或自动驾驶车辆的能源调度策略。
此实现通过一次遍历即完成计算,结合总油量验证和贪心策略,确保在 O(n) 时间复杂度内找到解。

浙公网安备 33010602011771号