Leetcode 134. 加油站
在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。
你有一辆油箱容量无限的的汽车,从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。
如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1。
说明:
- 如果题目有解,该答案即为唯一答案。
- 输入数组均为非空数组,且长度相同。
- 输入数组中的元素均为非负数。
示例 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: 输入:
- 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 升汽油。因此,无论怎样,你都不可能绕环路行驶一周。
解题思路:
这道题属于经典的加油站问题(Gas Station Problem),可以通过贪心算法来解决。
我们需要找到一个起始加油站,使得从这个加油站出发,能够绕环路行驶一周。首先,我们可以观察到以下两点性质:
- 如果整个环路上所有加油站的汽油总量大于等于整个环路上所有消耗的汽油总量,那么一定存在一个起始加油站可以绕行一周。
- 如果从某个加油站出发,无法到达下一个加油站(即当前加油站的汽油不足以抵消消耗的汽油),那么从这个加油站到下一个加油站之间的任何一个加油站都不能作为起始加油站。
基于以上性质,我们可以使用贪心算法来求解。算法的步骤如下:
- 初始化两个变量:
totalTank
表示油箱中的汽油总量,currTank
表示当前油箱中的汽油量,同时将起始加油站的索引startStation
设为 0。 - 遍历加油站,从 0 到 N-1:
- 在当前加油站,将当前油箱中的汽油加上
gas[i]
,并减去消耗的汽油量cost[i]
。 - 如果当前油箱中的汽油不足以到达下一个加油站(即
currTank < 0
),则将起始加油站设为下一个加油站的索引,并将currTank
重置为 0。 - 更新
totalTank
和currTank
。
- 在当前加油站,将当前油箱中的汽油加上
- 最后,检查
totalTank
是否大于等于0
,如果是,则返回起始加油站的索引startStation
,否则返回-1
。
下面是对示例输入的解题过程:
输入:
gas = [1, 2, 3, 4, 5]
cost = [3, 4, 5, 1, 2]
初始化变量:
totalTank = 0
currTank = 0
startStation = 0
遍历加油站:
加油站 0:
totalTank += gas[0] - cost[0] = 1 - 3 = -2
currTank += gas[0] - cost[0] = 1 - 3 = -2
currTank < 0,更新 startStation = 1,currTank = 0
加油站 1:
totalTank += gas[1] - cost[1] = 2 - 4 = -2
currTank += gas[1] - cost[1] = 2 - 4 = -2
currTank < 0,更新 startStation = 2,currTank = 0
加油站 2:
totalTank += gas[2] - cost[2] = 3 - 5 = -2
currTank += gas[2] - cost[2] = 3 - 5 = -2
currTank < 0,更新 startStation = 3,currTank = 0
加油站 3:
totalTank += gas[3] - cost[3] = 4 - 1 = 3
currTank += gas[3] - cost[3] = 4 - 1 = 3
加油站 4:
totalTank += gas[4] - cost[4] = 5 - 2 = 6
currTank += gas[4] - cost[4] = 5 - 2 = 3
最后,totalTank = 6,大于等于 0,返回 startStation = 3,即加油站索引为 3。
因此,从加油站 3 出发可以绕环路行驶一周。
代码实现:
public class GasStation {
public int canCompleteCircuit(int[] gas, int[] cost) {
int startStation = 0; // 起始加油站索引
int totalTank = 0; // 油箱中的总油量
int currTank = 0; // 当前油箱中的油量
for (int i = 0; i < gas.length; i++) {
int diff = gas[i] - cost[i]; // 计算油量差
totalTank += diff; // 更新总油量
currTank += diff; // 更新当前油量
// 如果当前油量不足以到达下一个加油站,则将起始加油站设为下一个加油站
if (currTank < 0) {
startStation = i + 1;
currTank = 0;
}
}
// 检查总油量是否大于等于 0
return totalTank >= 0 ? startStation : -1;
}
public static void main(String[] args) {
GasStation gasStation = new GasStation();
int[] gas = {1, 2, 3, 4, 5};
int[] cost = {3, 4, 5, 1, 2};
int startStation = gasStation.canCompleteCircuit(gas, cost);
System.out.println("Start station: " + startStation);
}
}
评论区