描述
在一条环路上有 N 个加油站,其中第 i 个加油站有汽油gas[i]
,并且从第_i_个加油站前往第_i_+1个加油站需要消耗汽油cost[i]
。
你有一辆油箱容量无限大的汽车,现在要从某一个加油站出发绕环路一周,一开始油箱为空。
求可环绕环路一周时出发的加油站的编号,若不存在环绕一周的方案,则返回-1
。
自己思路:采取的贪心策略就是看curGas,如果汽油可以一直累计>=0 那么就是可行的,如果到第i步汽油累积量变负,说明i及i以前的加油站都不能出发
public int canCompleteCircuit(int[] gas, int[] cost) {
// write your code here 要确认从该点出发后,会不会在后面的加油站卡住没油了!
int startIndex = -1;
int curGas = 0;
for (int i = 0; i < gas.length; i++) {
int diff = gas[i] - cost[i];
if (diff > 0){
if (startIndex == -1)
startIndex = i;
curGas += diff;
}else if (diff <= 0){
if (curGas + diff >= 0 && curGas > 0)
curGas+= diff;
else{
curGas = 0;
startIndex = -1;
}
}
}
return startIndex;
}
dalao思路:要考虑清楚问题的本质,开始出发的加油站一定是最后一个sum< 0 的后一个站,因为sum是加起来的总和,就算前面有一次使得sum > 0 ,但是之后sum 又小于0 说明前一次变正的加油站出发后仍然会卡住
public int canCompleteCircuit2(int[] gas, int[] cost) {
if (gas == null || cost == null || gas.length == 0 || cost.length == 0) {
return -1;
}
int sum = 0;
int total = 0;
int index = -1;
for(int i = 0; i<gas.length; i++) {
sum += gas[i] - cost[i];
total += gas[i] - cost[i];
if(sum < 0) {
index = i;
sum = 0;
}
}
return total < 0 ? -1 : index + 1;
// index should be updated here for cases ([5], [4]);
// total < 0 is for case [2], [2]
}
summary:
1、感觉情况比较复杂的时候,就耐心思考把所有情况列出来,这样做题才有用
2、在这样需要考虑未来的题中,不可能一下就出结果,采取贪心策略,如果当前满足就把入口定在当前,当不满足的时候就换入口并再次初始化相关变量,说的有点抽象,简单的想就是需要一个变量记录当前累积量,还需要一个变量记录当前满足条件的入口,根据累积量和题目条件在合适的时候换入口
3、有时候复杂的情况本质是一样的,如果前面行得通后面行不通,那么也相当于行不通,如果前面行不通,就更不用纠结前面过程中会不会有某个点行得通,只看后面就行
4、dalao的一个sum变量就取消了复杂的条件判断因为问题的本质是该在那个加油站出发,使得以后的汽油也够,那本质就是所有剩余量加起来不小于0,sum<0 。累积性问题,注意累积量的本质性