[LeetCode] 134. 加油站

最暴力的办法是需要枚举每一个起点,然后判断从该起点出发能否满足题意。
从暴力算法出发,如何优化呢?

  1. 可以不需要枚举每一个起点吗?
    不可以,每一个起点的枚举肯定是少不了的
  2. 枚举每一个起点后,判断可能性时可以优化吗
    可能很快能想到前缀和,能做到O(1)下判断从该点出发后,到最后一个加油站时剩余油量。但是剩余油量>=0就代表满足题意了吗?不是的,很容易就想到反例。

实际上,两层循环是少不了的。但是我们可以进行剪枝:

  1. 找到第一个符合题意的答案就直接输出
  2. 当油不够时可以直接退出内循环。

实际上,经过一些数学推导,最终的时间复杂度是能做到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;
    }
}
posted @ 2021-06-06 23:38  ACBingo  阅读(30)  评论(0编辑  收藏  举报