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

相关推荐
Solitudefire1 小时前
蓝桥杯刷题——day6
职场和发展·蓝桥杯
一行玩python1 小时前
PugiXML,一个高效且简单的 C++ XML 解析库!
xml·开发语言·c++·算法
Sunyanhui11 小时前
牛客网 SQL1查询所有列
c++·算法
所有向日癸上升2 小时前
问题 C: B001 快乐的蠕虫
c语言·开发语言·算法
Cooloooo2 小时前
二叉搜索树Ⅲ【东北大学oj数据结构8-3】C++
数据结构·c++·算法
互联网杂货铺2 小时前
单元测试总结
自动化测试·软件测试·python·测试工具·职场和发展·单元测试·测试用例
sjsjs114 小时前
【多维DP】力扣2370. 最长理想子序列
算法·leetcode·动态规划
在西湖雾雨中起舞4 小时前
题目 2834: 与指定数字相同的数的个数
数据结构·c++·算法
抓个马尾女孩4 小时前
Python中列表复制A=B和A=B[:]的区别
数据结构·python·算法
陌繁5 小时前
LeetCode1.两数之和(超简单讲解)
数据结构·算法·leetcode