【LeetCode-贪心】加油站

题目描述

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

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

如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -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 可为起始索引。

题目链接: https://leetcode-cn.com/problems/gas-station/

思路1

假设起始点为 i,则起始点的油量 gas[i] 一定是大于等于消耗 cost[i] 的,所以我们先找到所有可能为起始点的位置。
记录当前油量 curGas,对于每一个起始点:

  • curGas = curGas + gas[i] - cost[i];
  • 如果 curGas 小于 0,则说明该起始点不符合要求;尝试下一个起始点;否则返回起始点;

如果所有的起始点都不行,则返回 -1.

代码如下:

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        vector<int> starts;
        int n = gas.size();
        for(int i=0; i<n; i++){
            if(gas[i]>=cost[i]) starts.push_back(i); // 找到所有可能的起始点
        }

        for(int i=0; i<starts.size(); i++){ // 尝试每一个可能的起始点
            int departion = starts[i];
            int curPos = starts[i];
            int curGas = gas[curPos] - cost[curPos];
            curPos = (curPos+1)%n;
            bool flag = true;
            while((curPos)%n!=departion){
                curGas += gas[curPos];
                curGas -= cost[curPos];
                if(curGas<0){
                    flag = false;
                    break;
                }
                curPos = (curPos+1)%n;
            }
            if(flag) return departion;
        }
        return -1;
    }
};

思路2

使用两个变量 totalGas 记录总的油量剩余,如果跑一边 totalGas<0,则说明无解;使用 curGas 表示从起始点 start 出发到当前位置 i 剩余的油量。如果 curGas<0,则说明从之前的起始点到当前位置不可行,需要寻找新的起始点,新的起始点设为 i+1.

这里有一个问题就是为什么新的起始点要设置为 i+1,而不设置为 [start, i] 之间的点,假设 j ∈ [start, i],则从 j 出发到 i 的 curGas 也会是小于 0 的。

当遍历结束时,如果 totalGas>0,则说明有解,返回记录的起始点;否则返回 -1.

代码如下:

class Solution {
public:
    int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
        int totalGas = 0;
        int curGas = 0;
        int start = 0;
        for(int i=0; i<gas.size(); i++){
            int rest = gas[i] - cost[i];
            totalGas += rest;
            curGas += rest;
            if(curGas<0){
                curGas = 0;
                start = i+1;
            }
        }
        return totalGas<0? -1:start;
    }
};
  • 时间复杂度:O(n)
  • 空间复杂度:O(1)
原文地址:https://www.cnblogs.com/flix/p/13276146.html