【Classic 150 刷题计划】 LeetCode 134. 加油站 | C++ 贪心算法与局部否决逻辑

LeetCode 134. 加油站

📌 题目描述

题目级别:中等

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

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

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

  • 示例 1:
    输入: gas = [1,2,3,4,5], cost = [3,4,5,1,2]
    输出: 3

💡 破题思路:贪心算法 (一次遍历)

如果使用暴力解法,枚举每个节点为起点去模拟跑一圈,时间复杂度是 O(N2)O(N^2)O(N2),会超时。

事实上,我们可以通过推导得出两个极其强大的结论,从而将复杂度降为 O(N)O(N)O(N):

  1. 总和 >= 0 必有解 :

    如果整条环路的总油量 sum(gas) 大于等于总消耗 sum(cost),那么一定存在一个起点能够跑完一圈。所以我们需要一个变量 tolGas 来记录全局的净油量,只要遍历结束后 tolGas >= 0,我们就放心大胆地返回计算出的起点。

  2. 局部亏损引发的连坐否决 :

    假设我们从起点 i 出发,一路开到了节点 j,但在准备前往 j+1 时发现油箱里的油变负数了。

    这不仅仅意味着 i 不能作为起点,更意味着从 i 到 j 之间的任何一个节点都不能作为起点!

    为什么?因为我们从 i 能够开到中间的节点 k,说明到达 k 时油箱里多多少少带着点剩余的油。带着剩余的油从 k 出发最终都倒在了 j,如果你清空油箱直接从 k 重新出发,绝对会死得更早。

    贪心策略 :一旦在节点 j 处 curGas < 0,直接将下一次尝试的起点跳跃到 j + 1,并将 curGas 清零重新累加。


💻 C++ 代码实现 (原汁原味作者版)

cpp 复制代码
class Solution {
public:
    int canCompleteCircuit(std::vector<int>& gas, std::vector<int>& cost) {
        int n = gas.size();
        
        // 记录从当前起点 st 出发后的局部净油量
        int curGas = 0;
        // 记录跑完全程的全局净油量
        int tolGas = 0;
        // 记录潜在的起点
        int st = 0;
        
        for (int i = 0; i < n; i ++ )
        {
            tolGas += gas[i] - cost[i];
            curGas += gas[i] - cost[i];

            // 一旦局部油量跌破 0,触发"连坐否决"
            if (curGas < 0)
            {
                curGas = 0; // 油箱清空,从下一个站重新开始计算
                st = i + 1; // [st, i] 区间内的所有站点全军覆没,新起点只能是 i + 1
            }
        }
        
        // 只要全局油量 >= 0,最终锁定下来的 st 就绝对是合法的
        return tolGas >= 0 ? st : -1;
    }
};
相关推荐
朝朝辞暮i5 小时前
C++ 第 23 课:class —— 开始真正进入面向对象
开发语言·c++·算法
郑同学的笔记6 小时前
【c++随笔28】strcmp 和 memcmp对比
开发语言·c++
随意起个昵称7 小时前
【背包dp】输出方案路径
c++·动态规划
朝朝辞暮i7 小时前
C++ 第 27 课:智能指针 shared_ptr
开发语言·c++·算法
by209998 小时前
学会使用std::string类,并理解其内部是如何管理字符串的详细阐述(上)
c++·笔记·字符串·类和对象·string
沙漠之主8 小时前
C++编程教学设计资料:从入门到实战的完整课程方案
java·前端·c++
朝朝辞暮i8 小时前
C++ 第 29 课:回调函数 Callback
开发语言·c++·算法
kaixin_learn_qt_ing8 小时前
C++多态实现原理
c++
无名猿8 小时前
unique_ptr 完全指南:独占所有权与零开销
c++·性能优化·内存管理·标准库·现代c++
笑鸿的学习笔记9 小时前
C++笔记之大块顺序写
java·c++·笔记