持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第24天,点击查看活动详情
题目:在一条环路上有n个加油站,规定第i个加油站里面有gas[i]升汽油。
现在有一辆不限定油箱容量的车,从第i个加油站开往下一个加油站需要耗费cost[i]升汽油,开始时油箱为空,可以选择从其中一个加油站出发。
给定加油站油量数组和耗费汽油数组,判断是否可以从其中一个加油站绕环路行驶一周,如果可以返回开始加油站编号,否则返回-1。
解题思路
本题使用暴力解法还是很简单的,我们只需要从头往后遍历,只要满足gas[i]>=cost[i],那必然可以作为起点,之后判断作为起点是否可以回到这个点即可,判断的方法是按照题目规则不断更新步伐和油量,依次循环,如果最终都没有满足条件的则返回-1。可得代码如下:
public int canCompleteCircuit(int[] gas, int[] cost) {
for(int i=0;i<gas.length;i++){
if(gas[i]>=cost[i]&&canComplete(gas, cost, i)) return i;
}
return -1;
}
public boolean canComplete(int[] gas, int[] cost, int start){
int curGas = gas[start];
int i = start;
while(curGas>=cost[i]){
curGas += gas[(i+1)%gas.length] - cost[i];
i = (i+1)%gas.length;
if(i==start) return true;
}
return false;
}
此方法的时间复杂度很高,达到了,最终在一个长案例那超时,无法通过。
转换思路,如果当前加油站的油量小于去往下一站的所需油量,那此站必然不可能可以作为起点,而如果我们从头到尾汽油总和减去需要耗费汽油总和,那必然可以满足绕圈的要求,因此我们只需要在不满足作为起点时更新起点和油量即可。可得代码如下:
public int canCompleteCircuit2(int[] gas, int[] cost) {
int start = 0;
int curSum = 0;
int totalSum = 0;
for(int i=0;i<gas.length;i++){
curSum += gas[i]-cost[i];
totalSum += gas[i] - cost[i];
if(curSum<0){
start = i+1;
curSum = 0;
}
}
if(totalSum<0) return -1;
return start;
}
最终时间复杂度为。