【貪心】B022_加油站(暴力 | 跳躍思維)

一、題目描述

There are N gas stations along a circular route, where the amount of gas at station i is gas[i].

You have a car with an unlimited gas tank and it costs cost[i] of gas to travel from station i to its next station (i+1). You begin the journey with an empty tank at one of the gas stations.

Return the starting gas station’s index if you can travel around the circuit once in the clockwise direction, otherwise return -1.

Note:

  • If there exists a solution, it is guaranteed to be unique.
  • Both input arrays are non-empty and have the same length.
  • Each element in the input arrays is a non-negative integer.
Input: 
gas  = [1,2,3,4,5]
cost = [3,4,5,1,2]

Explanation:
Start at station 3 (index 3) and fill up with 4 unit of gas. Your tank = 0 + 4 = 4
Travel to station 4. Your tank = 4 - 1 + 5 = 8
Travel to station 0. Your tank = 8 - 2 + 1 = 7
Travel to station 1. Your tank = 7 - 3 + 2 = 6
Travel to station 2. Your tank = 6 - 4 + 3 = 5
Travel to station 3. The cost is 5. Your gas is just enough to travel back to station 3.
Therefore, return 3 as the starting index.

二、題解

方法一:枚舉

  • 枚舉每一個起點,判斷是否能回到起點。
  • 在每一個起點中,每次到一個加油站 k+1,就將剩餘油量 redius 加上 gas[k+1],然後減去當期位置的耗油量 cost[k]
public int canCompleteCircuit(int[] gas, int[] cost) {
    int N = gas.length;
    for (int i = 0; i < N; i++) {
        int k = i;
        int redius = gas[i];
        while (redius >= cost[k]) {
            redius -= cost[k];
            k = (k + 1) % N;
            redius += gas[k];
            if (k == i)
                return i;
        }
    }
    return -1;
}

複雜度分析

  • 時間複雜度:O(n2)O(n^2)
  • 空間複雜度:O(1)O(1)

方法二:貪心

在方法一的邏輯中,如果 i 不能到達某一個點,那麼算法會繼續枚舉 i+1 是否能到,這似乎是一個冗餘的過程。爲什麼?

假設 i = 0i 最遠能到達編號爲 4 的 gas_station,那麼從 ii+1 時 tank 裏面的油一定滿足 tank >= 0,那麼重點來了,在 i+1 時 tank 的油量 tank >= 0 都不能到達 4,從 i+1 白手起家也就不能到達 4 了!

所以,當 i 不能走到某個點 k 時,下次循環直接從 k 開始,避免繼續枚舉 [i+1, k) 中無效的起始點。

爲什麼不用取模來循環?因爲我們在算法的開始已經確定一定存在某個點 i 可以走完整個 circle,所以當利用排除法只用枚舉 1 遍區間 [0, N-1] 一定會找到一個合法起始點。

public int canCompleteCircuit(int[] gas, int[] cost) {
    int costs = 0, gases = 0, N = gas.length;
    for (int i = 0; i < N; i++) {
        gases += gas[i];
        costs += cost[i];
    }
    if (gases < costs)
        return -1;
    int cur = 0, begin = 0;
    for (int i = 0; i < N; i++) {
        cur += gas[i];
        cur -= cost[i];
        if (cur < 0) {
            cur = 0;
            begin = i + 1;
        }
    }
    return begin;
}

複雜度分析

  • 時間複雜度:O(n)O(n)
  • 空間複雜度:O(1)O(1)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章