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 时,通过取余可以将索引正确地映射回环形路线中的有效站点索引范围,确保返回的是一个合法的可以作为起始站点的索引值。

相关推荐
闻缺陷则喜何志丹1 小时前
【SOSDP模板 容斥原理 逆向思考】3757. 有效子序列的数量|分数未知
c++·算法·力扣·容斥原理·sosdp·逆向思考
CoovallyAIHub1 小时前
如何在手机上轻松识别多种鸟类?我们发现了更简单的秘密……
深度学习·算法·计算机视觉
第二只羽毛1 小时前
遵守robots协议的友好爬虫
大数据·爬虫·python·算法·网络爬虫
艾斯比的日常2 小时前
Java 三色标记算法:并发垃圾回收的核心技术解析
java·开发语言·算法
CoovallyAIHub2 小时前
抛弃LLM!MIT用纯视觉方法破解ARC难题,性能接近人类水平
深度学习·算法·计算机视觉
程序猿编码2 小时前
PRINCE算法的密码生成器:原理与设计思路(C/C++代码实现)
c语言·网络·c++·算法·安全·prince
高洁012 小时前
具身智能-视觉语言导航(VLN)
深度学习·算法·aigc·transformer·知识图谱
Hacker_Oldv2 小时前
API 自动化测试难点总结与分享
自动化测试·软件测试·职场和发展
Croa-vo2 小时前
TikTok 数据工程师三轮 VO 超详细面经:技术深挖 + 建模推导 + 压力测试全记录
javascript·数据结构·经验分享·算法·面试
蘑菇小白2 小时前
时间复杂度
数据结构·算法