134. 加油站
题目:
思路:
【1】常规的方式(但是容易出现超时的现象)
【2】通过累计总油量-耗油量的方式判断
代码展示:
常规的方式:
//时间复杂度:O(N^2),其中 N 为数组的长度。我们对数组进行了二次遍历。 //空间复杂度:O(1)。 //这种存在大量的重复遍历,而且一旦数据量庞大的话会导致耗费时间急剧上升 class Solution { public int canCompleteCircuit(int[] gas, int[] cost) { int n = gas.length; for (int i = 0; i < n ; i++){ if (gas[i] >= cost[i]){ //获得初始油量 int tank = gas[i] - cost[i]; //记录出发下标 int index = i; while (tank >= 0 && (++index)%n != i){ tank += gas[index%n] - cost[index%n]; } //如果在油耗尽前能回到出发地,即返回下标 if (index%n == i){ return i; } } } return -1; } }
通过累计总油量-耗油量的方式判断:
//时间3 ms 击败 36.67% //内存53.7 MB 击败 88.25% //时间复杂度:O(N),其中 N 为数组的长度。我们对数组进行了单次遍历。 //空间复杂度:O(1)。 class Solution { public int canCompleteCircuit(int[] gas, int[] cost) { int n = gas.length; int i = 0; while (i < n) { // 总共加的油 和 总共消费的油 int sumOfGas = 0, sumOfCost = 0; // 记录能走过几个站点 int cnt = 0; // 退出循环的条件是走过所有的站 while (cnt < n) { // 加油站是环形的 int j = (i + cnt) % n; sumOfGas += gas[j]; sumOfCost += cost[j]; // 如果这个站点发现油不够了 if (sumOfCost > sumOfGas) { break; } // 这个站点满足情况 cnt++; } // 如果能环绕一圈 if (cnt == n) { return i; } else { // 不行的话 从下一个站点开始 检查(这里便是最大的改良点) // 如果之前已经走过的地方便会跳过不重复走 i = i + cnt + 1; } } // 所有加油站作为起点都不满足 return -1; } } //时间1 ms 击败 100% //内存54.1 MB 击败 68.7% class Solution { public int canCompleteCircuit(int[] gas, int[] cost) { int len = gas.length; int ls = 0; int sum = 0; int i = 0; int x = 0; while(i<len){ sum = sum + gas[i] - cost[i]; i++; if(sum < 0){ ls += sum; sum = 0; x = i; } } if(ls + sum >=0){ return x; } return -1; } }