【陪伴式刷题】Day 30|贪心算法|134.加油站(Gas Station)

558 阅读4分钟

刷题顺序按照代码随想录建议

题目描述

英文版描述

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

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

Given two integer arrays gas and cost, return the starting gas station's index if you can travel around the circuit once in the clockwise direction, otherwise return -1. If there exists a solution, it is guaranteed to be unique

Example 1:

Input: gas = [1,2,3,4,5], cost = [3,4,5,1,2] Output: 3 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.

Example 2:

Input: gas = [2,3,4], cost = [3,4,3] Output: -1 Explanation: You can't start at station 0 or 1, as there is not enough gas to travel to the next station. Let's start at station 2 and fill up with 4 unit of gas. Your tank = 0 + 4 = 4 Travel to station 0. Your tank = 4 - 3 + 2 = 3 Travel to station 1. Your tank = 3 - 3 + 3 = 3 You cannot travel back to station 2, as it requires 4 unit of gas but you only have 3. Therefore, you can't travel around the circuit once no matter where you start.

Constraints:

  • gas.length == n
  • cost.length == n
  • 1 <= n <= 10^5
  • 0 <= gas[i], cost[i] <= 10^4

英文版地址

leetcode.com/problems/ga…

中文版描述

在一条环路上有 n 个加油站,其中第 i 个加油站有汽油 gas[i] **升。

你有一辆油箱容量无限的的汽车,从第 **i **个加油站开往第 **i+1 **个加油站需要消耗汽油 cost[i] **升。你从其中的一个加油站出发,开始时油箱为空。

给定两个整数数组 gascost ,如果你可以按顺序绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1 。如果存在解,则 保证 它是 唯一 的。

示例 1:

输入: gas = [1,2,3,4,5], cost = [3,4,5,1,2] 输出: 3 解释: 从 3 号加油站(索引为 3 处)出发,可获得 4 升汽油。此时油箱有 = 0 + 4 = 4 升汽油 开往 4 号加油站,此时油箱有 4 - 1 + 5 = 8 升汽油 开往 0 号加油站,此时油箱有 8 - 2 + 1 = 7 升汽油 开往 1 号加油站,此时油箱有 7 - 3 + 2 = 6 升汽油 开往 2 号加油站,此时油箱有 6 - 4 + 3 = 5 升汽油 开往 3 号加油站,你需要消耗 5 升汽油,正好足够你返回到 3 号加油站。 因此,3 可为起始索引。

示例 2:

输入: gas = [2,3,4], cost = [3,4,3] 输出: -1 解释: 你不能从 0 号或 1 号加油站出发,因为没有足够的汽油可以让你行驶到下一个加油站。 我们从 2 号加油站出发,可以获得 4 升汽油。 此时油箱有 = 0 + 4 = 4 升汽油 开往 0 号加油站,此时油箱有 4 - 3 + 2 = 3 升汽油 开往 1 号加油站,此时油箱有 3 - 3 + 3 = 3 升汽油 你无法返回 2 号加油站,因为返程需要消耗 4 升汽油,但是你的油箱只有 3 升汽油。 因此,无论怎样,你都不可能绕环路行驶一周。

提示:

  • gas.length == n
  • cost.length == n
  • 1 <= n <= 10^5
  • 0 <= gas[i], cost[i] <= 10^4

中文版地址

leetcode.cn/problems/ga…

解题方法

法1

class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        if (gas == null) {
            return -1;
        }
        int curSum = 0;
        int sum = 0;
        int result = 0;
        int length = gas.length;
        for (int i = 0; i < length; i++) {
            curSum = curSum + gas[i] - cost[i];
            sum = sum + gas[i] - cost[i];
            if (curSum < 0) {
                curSum = 0;
                result = i + 1;
            }
        }
        if (sum < 0) {
            return -1;
        } else {
            return result;
        }
    }
}

难点说明:这种解法比较难懂的就是for循环中if判断的部分,curSum<0 说明了从前面的任意加油站无法到达当前加油站,所以我们只能从当前的下一个继续判断,于是将起始坐标重置为下一加油站的序号,并重新将curSum置为0

复杂度分析

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

法2

class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        int sum = 0;
        int min = 0;
        for (int i = 0; i < gas.length; i++) {
            sum += (gas[i] - cost[i]);
            min = Math.min(sum, min);
        }

        if (sum < 0) return -1;
        if (min >= 0) return 0;

        for (int i = gas.length - 1; i > 0; i--) {
            min += (gas[i] - cost[i]);
            if (min >= 0) return i;
        }

        return -1;
    }
}

复杂度分析

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

法3

法3其实是法 1的一个变式(Leetcode官网评论区一位名叫“潇”的用户写的,感觉感觉还挺巧妙)

class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        int sum = 0;
        int index = 0;
        int max = Integer.MIN_VALUE;
        for(int i=gas.length-1; i>=0; i--){
            sum += gas[i] - cost[i];
            if(sum > max){
                max = sum;
                index = i;
            }
        }
        return sum >= 0 ? index : -1;
    }
}

复杂度分析

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)