题目
在一条环路上有 n
个加油站,其中第 i
个加油站有汽油 gas[i]
升。
你有一辆油箱容量无限的的汽车,从第 i
个加油站开往第 i+1
个加油站需要消耗油 cost[i]
升。你从其中的一个加油站出发,开始时油箱为空。给定两个整数数组 gas
和 cost
,如果你可以按顺序绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1
。如果存在解,则 保证 它是 唯一 的。
暴力法思路-超时
-
计算剩余油量:
- 用
gasleft[i] = gas[i] - cost[i];
计算每个站点的剩余油量。
- 用
-
遍历起始点:
- 外层循环遍历每个可能的起始点
i
,内层循环从该点出发,使用k
来模拟行驶过程。
- 外层循环遍历每个可能的起始点
-
检查油量:
- 在内层循环中,使用
total
来追踪剩余油量。如果在行驶过程中total
小于零,退出内层循环。
- 在内层循环中,使用
-
返回结果:
- 如果能完整绕行一圈,返回起始点
i
,否则返回-1
。
- 如果能完整绕行一圈,返回起始点
复杂度分析
- 时间复杂度:O(n^2),在最坏情况下,您需要对每个起始点进行 n 次检查。
- 空间复杂度:O(n),存储
gasleft
数组。
代码:
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int n=cost.size();
vector<int>gasleft(n);
for(int i=0;i<n;i++){
gasleft[i]=gas[i]-cost[i];
}
for(int i=0;i<n;i++){
int total=0;
int k;
for(k=0;k<n;k++){
int j=(i+k)%n;
total+=gasleft[j];
if(total<0)break;
}
if(k==n)return i;
}
return -1;
}
};
贪心思路解答:
-
贪心算法:
- 可以通过一次遍历来找到能否完成环路。如果在从某个起始点出发时,
total
小于零,说明从这个起始点无法完成环路,因此直接跳过这个起始点。
- 可以通过一次遍历来找到能否完成环路。如果在从某个起始点出发时,
-
更新起始点:
- 如果在某个点无法继续前进,则将起始点更新为下一个点。并且在更新起始点后,重置
total
为零,继续判断。
- 如果在某个点无法继续前进,则将起始点更新为下一个点。并且在更新起始点后,重置
#include <vector>
using namespace std;
class Solution {
public:
int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
int n = gas.size();
int totalGas = 0, totalCost = 0;
int currentGas = 0;
int startIndex = 0;
for (int i = 0; i < n; i++) {
totalGas += gas[i];
totalCost += cost[i];
currentGas += gas[i] - cost[i];
// 如果当前的油量不足以到达下一个站点
if (currentGas < 0) {
// 将起始点更新为下一个站点
startIndex = i + 1;
currentGas = 0; // 重置当前油量
}
}
// 如果总油量不足以完成环路,返回 -1
if (totalGas < totalCost) {
return -1;
}
return startIndex;
}
};
代码说明:
-
总油量和总成本:
totalGas
和totalCost
用于计算整个环路的总油量和总成本。
-
当前油量:
currentGas
用于跟踪从当前起始点出发能否到达下一个站点。
-
更新起始点:
- 如果在某个点无法继续,更新起始点为下一个站点,重置当前油量。
-
判断是否能完成环路:
- 如果总油量小于总成本,直接返回
-1
,表示无法完成环路。
- 如果总油量小于总成本,直接返回
贪心复杂度分析
- 时间复杂度:O(n),只需遍历一次数组。
- 空间复杂度:O(1),只使用了少量额外的变量。
-
这道题主要就是由x到y不满足条件,那么(x,y)阶段的所有节点出发都不会满足条件。