[LeetCode] 134. 加油站
最暴力的办法是需要枚举每一个起点,然后判断从该起点出发能否满足题意。
从暴力算法出发,如何优化呢?
- 可以不需要枚举每一个起点吗?
不可以,每一个起点的枚举肯定是少不了的 - 枚举每一个起点后,判断可能性时可以优化吗
可能很快能想到前缀和,能做到O(1)下判断从该点出发后,到最后一个加油站时剩余油量。但是剩余油量>=0就代表满足题意了吗?不是的,很容易就想到反例。
实际上,两层循环是少不了的。但是我们可以进行剪枝:
- 找到第一个符合题意的答案就直接输出
- 当油不够时可以直接退出内循环。
实际上,经过一些数学推导,最终的时间复杂度是能做到O(n)的,因为前面不符合题意的起始点都不会跑完2层循环
class Solution {
public int canCompleteCircuit(int[] gas, int[] cost) {
int n = gas.length;
if (n == 0) return -1;
int[] f = new int[n];
for (int i=0;i<n;i++) {
f[i] = gas[i] - cost[i];
}
int[] sum = new int[n];
sum[0] = f[0];
for (int i=1;i<n;i++) {
sum[i] = sum[i-1] + f[i];
}
if (sum[n-1] < 0) return -1;
for (int i = 0;i<n;i++) {
if (f[i] >= 0) {
int tmp = 0;
int k = 0;
for (k = 0;k<n;k++) {
tmp+=f[(i+k)%n];
if (tmp < 0) break;
}
if (k==n) return i;
}
}
return -1;
}
}