代码训练(25)LeetCode之加油站
Author: Once Day Date: 2025年6月9日
漫漫长路,才刚刚开始…
全系列文章可参考专栏: 十年代码训练_Once-Day的博客-CSDN博客
参考文章:
1. 原题
在一条环路上有
n
个加油站,其中第i
个加油站有汽油gas[i]
升。你有一辆油箱容量无限的的汽车,从第
i
个加油站开往第i+1
个加油站需要消耗汽油cost[i]
升。你从其中的一个加油站出发,开始时油箱为空。给定两个整数数组
gas
和cost
,如果你可以按顺序绕环路行驶一周,则返回出发时加油站的编号,否则返回-1
。如果存在解,则 保证 它是 唯一 的。提示:
n == gas.length == cost.length
1 <= n <= 105
0 <= gas[i], cost[i] <= 104
- 输入保证答案唯一。
示例:
输入: 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 可为起始索引。
输入: gas = [2,3,4], cost = [3,4,3]
输出: -1
解释:
你不能从 0 号或 1 号加油站出发,因为没有足够的汽油可以让你行驶到下一个加油站。
我们从 2 号加油站出发,可以获得 4 升汽油。 此时油箱有 = 0 + 4 = 4 升汽油
开往 0 号加油站,此时油箱有 4 - 3 + 2 = 3 升汽油
开往 1 号加油站,此时油箱有 3 - 3 + 3 = 3 升汽油
你无法返回 2 号加油站,因为返程需要消耗 4 升汽油,但是你的油箱只有 3 升汽油。
因此,无论怎样,你都不可能绕环路行驶一周。
2. 分析
这个问题可以理解为一个环形道路上存在一系列加油站,你有一辆汽车需要从某个加油站出发,且油箱初始为空,尝试绕环路行驶一周。给定两个数组gas
和cost
,gas[i]
表示在第i
个加油站可以加的油量,而cost[i]
表示从第i
个加油站到下一个加油站所需的油量。你需要确定是否存在一个起始点使得汽车能够绕环一周并回到起始点,如果可以,返回起始加油站的索引;如果不可以,返回-1
这个问题可以通过计算总的油量净增是否非负来判断是否可能存在这样的起点。如果总的gas
减去总的cost
是非负的,那么一定存在这样的起点。问题的关键是如何找到这个起起点。
解题思路
- 总油量检查:首先计算所有加油站的油量之和与消耗的油量之和。如果总消耗大于总油量,那么不可能绕一圈,返回-1。
- 寻找起始点:
- 从第0个加油站开始尝试,计算当前的油量(当前油量 = 加的油 - 消耗的油)。
- 如果在某个点的当前油量为负,说明从之前的起始点出发不可能到达这个点,需要将起始点设为当前点的下一个。
- 重新计算当前油量直到遍历完所有加油站。
分析步骤
- 初始化总油量
totalTank
和当前油量currTank
为0,起始点startStation
为0。 - 遍历所有加油站:
- 更新
totalTank
和currTank
。 - 如果
currTank
< 0,将startStation
设置为当前加油站的下一个,并重置currTank
。
- 更新
- 最后,如果
totalTank
>= 0,返回startStation
;否则返回-1。
示例分析
假设 gas = [1,2,3,4,5]
, cost = [3,4,5,1,2]
:
- 从加油站0出发,无法到达下一个加油站,因为1-3 = -2。
- 尝试从1开始,同理无法到达下一个加油站,因为2-4 = -2。
- 从2开始,同样因为3-5 = -2无法前进。
- 从3出发,可以一直走完一圈。此时为正确答案。
3. 代码实现
#include <stdio.h>
int canCompleteCircuit(int* gas, int* cost, int n) {
int totalTank = 0;
int currTank = 0;
int startStation = 0;
for (int i = 0; i < n; i++) {
totalTank += gas[i] - cost[i];
currTank += gas[i] - cost[i];
if (currTank < 0) {
startStation = i + 1;
currTank = 0;
}
}
return (totalTank >= 0) ? startStation : -1;
}
int main() {
int gas[] = {1,2,3,4,5};
int cost[] = {3,4,5,1,2};
int n = 5;
int start = canCompleteCircuit(gas, cost, n);
printf("Start station: %d\n", start); // Expected output: 3
return 0;
}
4. 总结
这道题考察了对问题的整体理解及单次遍历数组解决问题的能力。通过理解每个加油站的油量变化对总旅程的影响,我们能有效地确定起始加油站。对于提升编程能力,理解问题的本质和尝试多种解决方案是关键。在实际应用中,这种类型的问题可用于资源分配和路径规划等场景。