134. Gas Station
一、题目
1、审题
2、分析
给出一个数组 gas,代表汽车在此地点可以加油 gas[i];一个数组 cost,代表汽车从此地点到达下一个地点需要耗费的油量 cost[i],设汽车油箱容量无限,求汽车顺时针能绕一圈的起始地点的下标。
二、解答
1、思路:
方法一、
运用两层循环。
第一层循环代表汽车的起始地点下标;
第二层循环判断汽车能否绕行一圈。
public int canCompleteCircuit(int[] gas, int[] cost) { int cur = 0; int len = gas.length; while(cur < len) { int tmp = cur; int gasTotal = 0; boolean flag = true; // 第一次进循环 while(tmp != cur || flag) { // 先加油、再耗油 gasTotal += gas[tmp] - cost[tmp]; if(gasTotal < 0) break; tmp++; tmp = tmp % len; flag = false; } if(gasTotal >= 0) return cur; cur++; } return -1; }
方法二、
有如下规律:
①、如果所有的 gas 之和 大于等于 cost 之和,则必定存在一条能循环绕一周的路径。
②、若从 A 出发不能到达 B,且 A 与 B 之间的地点均不可到达 B,则 A 与 B之间的地点均不能作为起始点。
public int canCompleteCircuit3(int[] gas, int[] cost) { //determine if we have a solution int total = 0; for (int i = 0; i < gas.length; i++) { total += gas[i] - cost[i]; } if (total < 0) { return -1; } // find out where to start int tank = 0; int start = 0; for (int i = 0; i < gas.length;i++) { tank += gas[i] - cost[i]; if (tank < 0) { start = i + 1; tank = 0; } } return start; }
方法三、
采用两个指针,start 从下标 0 开始, end 从下标 len - 1 开始。变量 sum 初始为 gas[end] - cost[end],即假使起始点为 end。
若 sum > 0, 则start 向后移动,且 sum 动态改变;
若 sum < 0,则 end 向前移动,且 sum 进行改变。
当 start >= end 时跳出循环,若 sum >= 0,即总的 gas >= cost,返回 end,否则 返回 -1,即不可达。
public int canCompleteCircuit4(int[] gas, int[] cost) { int end = gas.length - 1; int start = 0; int sum = gas[end] - cost[end]; while(start < end) { if(sum >= 0) { sum += gas[start] - cost[start]; ++start; } else { --end; sum += gas[end] - cost[end]; } } return sum >= 0 ? end : -1; }