news 2026/5/10 21:28:46

贪心算法专题(八):绝处逢生的起点——「加油站」

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
贪心算法专题(八):绝处逢生的起点——「加油站」

哈喽各位,我是前端小L。

欢迎来到贪心算法专题第八篇!

题目描述很长,但核心很简单:

有一些加油站围成一个圈。

  • gas[i]:第i站有多少油。

  • cost[i]:从第i站开到第i+1站要耗多少油。

  • 你有一辆油箱无限大的车。

  • 目标:找一个起点,让你能绕圈跑完一周。如果找不到,返回 -1。

力扣 134. 加油站

https://leetcode.cn/problems/gas-station/

题目分析:

  • 输入:两个整数数组gascost

  • 输出:起始加油站的下标(唯一解)。

例子:

gas = [1, 2, 3, 4, 5]

cost = [3, 4, 5, 1, 2]

  • 从下标 3(油4,耗1)出发:

    • 到下标 4:剩 3,加 5,剩 8。耗 2。

    • 到下标 0:剩 6,加 1,剩 7。耗 3。

    • ... 一路顺风。返回 3。

核心思维:归零与跳跃

首先,有一个全局的硬性条件:

如果所有站点的总油量 sum(gas) 小于总消耗 sum(cost),那神仙也跑不完一圈。 直接返回 -1。

接下来是贪心的核心逻辑:局部最优推导。

我们维护一个 curSum(当前油箱余额)。

假设我们需要从 i 站出发。

  1. 我们计算gas[i] - cost[i],这是这一站的净剩油量

  2. 我们累加这个净剩量到curSum

  3. 如果curSum < 0

    • 说明车在这一站(假设是j)抛锚了。

    • 关键推断:从ij之间的任何一个站点k,都不可能作为起点!

    • 为什么?因为如果你从i出发,到达k时,你的油箱里一定有>= 0的油(否则你早在k之前就抛锚了)。带着这些“遗产”油你都在j站死掉了,如果你直接从k站白手起家(初始油量为0),你在j站只会死得更惨!

    • 策略:既然ij都不行,那我们就把起点设为j + 1,并把curSum归零,重新开始尝试。

[图解逻辑:A -> ... -> B (死) => 起点直接跳到 B+1]

算法流程

  1. 初始化:

    • curSum = 0:当前连续路段的累积剩余油量。

    • totalSum = 0:全局的总剩余油量(用于最后判断是否有解)。

    • start = 0:我们假设的起点。

  2. 遍历所有加油站i

    • 计算当前站的净收益:rest = gas[i] - cost[i]

    • totalSum += rest

    • curSum += rest

    • 贪心判断:如果curSum < 0

      • 说明从starti这段路走不通。

      • 更换起点start = i + 1

      • 重置当前累积curSum = 0

  3. 最终判断

    • 循环结束后,如果totalSum < 0,说明总油不够,返回 -1。

    • 否则,返回我们最后确定的start。(只要总油够,且我们找到了一段路能一直走到终点,那么数学上可以证明,从这个start绕回前面的路也是通的)。

代码实现 (C++)

C++

#include <vector> using namespace std; class Solution { public: int canCompleteCircuit(vector<int>& gas, vector<int>& cost) { int curSum = 0; int totalSum = 0; int start = 0; for (int i = 0; i < gas.size(); i++) { // 计算当前站点的净剩油量 int rest = gas[i] - cost[i]; totalSum += rest; curSum += rest; // 贪心策略:如果累积油量小于0,说明从 start 到 i 的区间无法连通 if (curSum < 0) { // 之前的努力全部作废,起点重置为下一个点 i + 1 start = i + 1; // 油箱归零 curSum = 0; } } // 全局判断:如果总油量不够总消耗,肯定无解 if (totalSum < 0) { return -1; } // 否则,最后确定的 start 就是唯一解 return start; } };

深度复杂度分析

  • 时间复杂度:O(N)

    • 我们只需要遍历一次数组。

    • 这比暴力法的 $O(N^2)$ 简直是质的飞跃。

  • 空间复杂度:O(1)

    • 只需要几个变量。

总结:相信数学,相信贪心

这道题最难理解的地方在于:为什么 totalSum >= 0 且 curSum 在最后一段非负,就一定能保证绕圈成功?

这涉及到一个数学证明:如果总和非负,那么一定存在一个起点,使得所有前缀和非负。我们通过贪心策略抛弃了所有“前缀和为负”的区间,剩下的那个起点,就是那个“天选之子”。

贪心算法在这里表现为:遇到困难(负数),立刻止损,跳过整段困难区间,寻找新的希望。


下一题预告:分发糖果

接下来这道题是贪心算法的Hard级别题目,也是面试中的“终极杀手”。

  • 一群孩子排排坐,每个孩子有评分。

  • 每个孩子至少一颗糖。

  • 相邻的孩子,评分高的必须获得更多的糖果。

  • 问最少需要多少糖?

这道题难就难在“相邻”是双向的(既要比左边多,又要比右边多)。

贪心策略教我们:不要试图同时顾及两边! 我们可以先从左往右遍历一次(只顾左边),再从右往左遍历一次(只顾右边),最后取最大值。

准备好分糖果了吗?下期见!

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/10 10:14:17

如何验证PyTorch是否成功调用GPU?torch.cuda.is_available()实测方法

如何验证PyTorch是否成功调用GPU&#xff1f;torch.cuda.is_available()实测方法 在深度学习项目启动的那一刻&#xff0c;最让人沮丧的莫过于——代码跑起来了&#xff0c;但GPU却没用上。训练速度慢得像爬行&#xff0c;日志里还找不到原因。你开始怀疑&#xff1a;显卡装了&…

作者头像 李华
网站建设 2026/5/10 3:30:58

如何避免PyTorch安装失败?使用PyTorch-CUDA-v2.7镜像规避依赖问题

如何避免PyTorch安装失败&#xff1f;使用PyTorch-CUDA-v2.7镜像规避依赖问题 在深度学习项目启动阶段&#xff0c;最令人沮丧的往往不是模型调参&#xff0c;而是环境配置——尤其是当你满怀期待地运行 import torch 却收到一条冰冷的 CUDA not available 提示时。这种“明明有…

作者头像 李华
网站建设 2026/5/10 5:58:31

人工智能应用-机器视觉:车牌识别(4)

基于深度神经网络的 YOLO 方法 基于传统图像处理方法的车牌定位不需要太多训练数据&#xff0c;但容易受到环境干扰&#xff0c;且在复杂场景下更容易出现判断错误。如果有较多的训练数据&#xff0c;可以考虑用神经网络模型&#xff0c;一般能获得更好的性能。 展示了一个卷积…

作者头像 李华
网站建设 2026/5/9 20:01:34

Jupyter Lab集成PyTorch环境:可视化开发更高效

Jupyter Lab集成PyTorch环境&#xff1a;可视化开发更高效 在深度学习项目中&#xff0c;你是否经历过这样的场景&#xff1f;好不容易写完一个模型训练脚本&#xff0c;运行后报错“CUDA out of memory”&#xff0c;却只能从头再跑一遍&#xff1b;或者团队成员说“我这边能跑…

作者头像 李华
网站建设 2026/5/9 15:14:09

我的2025,All In 鸿蒙

大家好&#xff0c;我是 V 哥。 2025年马上翻篇了&#xff0c;25年&#xff0c;不是"接着奏乐接着舞"&#xff0c;更像是“饿着舞”&#xff0c;《鸿蒙星光盛典》上黄渤的这段话相信很多小伙伴都能共鸣。我知道这些年的路&#xff0c;大家是怎么一步一步走过来的。对…

作者头像 李华