Leetcode经典题11--加油站

题目描述

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

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

给定两个整数数组 gas 和 cost ,如果你可以按顺序绕环路行驶一周,则返回出发时加油站的编号,否则返回 -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 可为起始索引。

解决方案

方式一:贪心

假设我们此前发现,从加油站 x 出发,每经过一个加油站就加一次油(包括起始加油站),最后一个可以到达的加油站是 y(不妨设 x<y)

第一个式子表明从x加油站出发无法到达加油站 y 的下一个加油站,

第二个式子表明可以到达 y 以及 y 之前的所有加油站。

现在,考虑任意一个位于 x,y 之间的加油站 z(包括 x 和 y),我们现在考察从该加油站出发,能否到达加油站 y 的下一个加油站

结论 为,如果从 加油站 x 出发无法到达 加油站 y ,则 x 和 y 之间的加油站也无法到达加油站 y

实现代码

复制代码
class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        int n = gas.length;//加油站的数量
        int i = 0;
        while (i < n) {//外层索引,判断从第i个站点作为起点,能否绕圈完成行程
        //sumOfGas总的加油量 sumOfCost 总的耗油量
            int sumOfGas = 0, sumOfCost = 0;
            int cnt = 0;   //经过的站点数量
            while (cnt < n) {
                int j = (i + cnt) % n;  //对应的加油站的索引
                sumOfGas += gas[j];
                sumOfCost += cost[j];
                if (sumOfCost > sumOfGas) {
                    break;//如果耗油量大于加油量,则不能实现绕圈
                }
                cnt++;
            }
            if (cnt == n) {
                return i;  //如果能绕圈的话,返回下标
            } else {
                i = i + cnt + 1;//根据结论,第i个加油站,无法到达第cnt个加油站,那么之间的加油站也是无法到达i+cnt个加油站的,所以直接从第i+cnt+1个加油占出发
            }
        }
        return -1;
    }
}

复杂度分析

时间复杂度:O(N),

其中 N 为数组的长度。我们对数组进行了单次遍历。

空间复杂度:O(1)。

方式二: 计算剩余油量

算法思想: 统计经过i个站点的剩余的油量,并且记录剩余油量最小的站点,如果剩余油量

实现代码

复制代码
class Solution {
    public int canCompleteCircuit(int[] gas, int[] cost) {
        int len = gas.length;
        int spare = 0;//遍历站点累积剩余的汽油量。
        int minSpare = Integer.MAX_VALUE;//遍历站点之后的最小剩余汽油量
        int minIndex = 0;//出现最小剩余汽油量时,对应的站点

        for (int i = 0; i < len; i++) {
            spare += gas[i] - cost[i];// 剩余的油量
            if (spare < minSpare) {
                minSpare = spare; // 最小的剩余油量
                minIndex = i;
            }
        }

        return spare < 0 ? -1 : (minIndex + 1) % len;
    }
}

spare < 0 ? -1 : (minIndex + 1) % len;

spare < 0:如果经过完整一轮遍历后,总的剩余汽油量 spare 是小于 0 的,这意味着在整个环形路线中,无论从哪个站点出发,按照给定的各站点汽油量和消耗情况,最终汽油都是不够用的,没办法绕一圈回到起点,所以此时返回 -1,表示不存在这样能完成环形路线的起始站点。

而如果 spare >= 0,说明整体上汽油量是足够绕一圈的。此时需要返回合适的起始站点索引,这里返回 (minIndex + 1) % len。之所以是 minIndex + 1,是因为我们记录的 minIndex 是出现最小剩余汽油量的那个站点索引

而从逻辑上分析,想要顺利绕圈,应该从这个最小剩余汽油量站点的下一个站点出发(因为在这个最小剩余站点处汽油量是最少的,往前汽油更少,所以往后一个站点出发更有可能绕圈成功),同时使用取余操作 % len 是因为这是环形路线,当 minIndex + 1 的值超过了站点数量 len 时,通过取余可以将索引正确地映射回环形路线中的有效站点索引范围,确保返回的是一个合法的可以作为起始站点的索引值。

相关推荐
木木子99992 分钟前
超平面(Hyperplane)是什么?
算法·机器学习·支持向量机·超平面·hyperplane
是乐谷1 小时前
阿里招AI产品运营
人工智能·程序人生·面试·职场和发展·产品运营·求职招聘
星空下的曙光1 小时前
React 虚拟 DOM Diff 算法详解,Vue、Snabbdom 与 React 算法对比
vue.js·算法·react.js
♞沉寂2 小时前
数据结构——双向链表
数据结构·算法·链表
大阳1232 小时前
数据结构2.(双向链表,循环链表及内核链表)
c语言·开发语言·数据结构·学习·算法·链表·嵌入式
CUC-MenG3 小时前
2025牛客多校第六场 D.漂亮矩阵 K.最大gcd C.栈 L.最小括号串 个人题解
c语言·c++·算法·矩阵
2401_876221343 小时前
Tasks and Deadlines(Sorting and Searching)
c++·算法
我要学习别拦我~4 小时前
逻辑回归建模核心知识点梳理:原理、假设、评估指标与实战建议
算法·机器学习·逻辑回归
张子夜 iiii4 小时前
机器学习算法系列专栏:决策树算法(初学者)
人工智能·python·算法·决策树·机器学习
KotlinKUG贵州4 小时前
贪心算法:从“瞎蒙”到稳赚
算法·kotlin