最佳加油站选择算法:解决环路加油问题的两种高效方法|LeetCode力扣134

简介: 最佳加油站选择算法:解决环路加油问题的两种高效方法|LeetCode力扣134

❤️❤️❤️ 欢迎来到我的博客。希望您能在这里找到既有价值又有趣的内容,和我一起探索、学习和成长。欢迎评论区畅所欲言、享受知识的乐趣!

期待与您一起探索技术、持续学习、一步步打怪升级 欢迎订阅本专栏❤️❤️

题目描述

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

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

如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -1。

注意:

  • 如果存在解,则保证该解为唯一的。

示例 1:

输入: 
gas  = [1,2,3,4,5]
cost = [3,4,5,1,2]
输出: 3
解释:
从 3 号加油站开始,可以获得 4 升汽油。出发后,油箱里有 4 升汽油。
开往 4 号加油站需要 1 升汽油,剩余 3 升汽油。
开往 5 号加油站需要 2 升汽油,剩余 1 升汽油。
开往 1 号加油站需要 3 升汽油,剩余 -2 升汽油。
开往 2 号加油站需要 4 升汽油,剩余 -1 升汽油。
开往 3 号加油站需要 5 升汽油,剩余 -6 升汽油。
由于油箱里有足够的汽油可以完成环路,所以返回 3。

示例 2:

输入: 
gas  = [2,3,4]
cost = [3,4,3]
输出: -1
解释:
你只能从 0 号或 1 号加油站出发,但都不能完成环路行驶一周。

方法一:贪心算法

解题步骤

  1. 初始化总油量 total_tank 和当前油量 curr_tank 为 0。
  2. 初始化起始站点 starting_station 为 0。
  3. 遍历每个加油站,计算 total_tankcurr_tank 分别增加当前站点的汽油量减去消耗量。
  4. 如果在某个站点 curr_tank 小于 0,说明无法从当前 starting_station 到达该站点,因此需要将 starting_station 更新为该站点的下一个站点,并将 curr_tank 置为 0。
  5. 遍历结束后,如果 total_tank 大于等于 0,返回 starting_station,否则返回 -1。

Python 示例

def canCompleteCircuit(gas, cost):
    total_tank, curr_tank = 0, 0
    starting_station = 0
    for i in range(len(gas)):
        total_tank += gas[i] - cost[i]
        curr_tank += gas[i] - cost[i]
        if curr_tank < 0:
            starting_station = i + 1
            curr_tank = 0
    return starting_station if total_tank >= 0 else -1
# Example usage
gas = [1, 2, 3, 4, 5]
cost = [3, 4, 5, 1, 2]
print(canCompleteCircuit(gas, cost))  # Output: 3
gas = [2, 3, 4]
cost = [3, 4, 3]
print(canCompleteCircuit(gas, cost))  # Output: -1

算法分析

  • 时间复杂度:O(N),其中 N 是加油站的数量。我们只需遍历一次所有的加油站。
  • 空间复杂度:O(1),只使用了常数级别的额外空间。

算法图解与说明

考虑 gas = [1, 2, 3, 4, 5], cost = [3, 4, 5, 1, 2]
总油量 total_tank = 0, 当前油量 curr_tank = 0, 起始站点 starting_station = 0
遍历每个加油站:
站点0: total_tank = -2, curr_tank = -2 (curr_tank < 0, 更新起始站点为1, curr_tank = 0)
站点1: total_tank = -4, curr_tank = -2 (curr_tank < 0, 更新起始站点为2, curr_tank = 0)
站点2: total_tank = -6, curr_tank = -2 (curr_tank < 0, 更新起始站点为3, curr_tank = 0)
站点3: total_tank = -3, curr_tank = 3 (curr_tank >= 0, 继续)
站点4: total_tank = 0, curr_tank = 4 (curr_tank >= 0, 继续)
总油量 total_tank >= 0,因此可以完成环路,返回起始站点3。

这种方法有效利用了贪心算法的思想,确保从正确的起始点开始能够完成环路行驶。

方法二:前缀和与一次遍历

解题步骤

  1. 初始化 total_tankcurr_tank 为 0,用于计算总油量和当前油量。
  2. 初始化起始站点 starting_station 为 0。
  3. 遍历每个加油站,计算从当前站点到下一个站点的油量差,并更新 total_tankcurr_tank
  4. 如果在某个站点 curr_tank 小于 0,说明无法从当前 starting_station 到达该站点。因此,将 starting_station 更新为该站点的下一个站点,并将 curr_tank 置为 0。
  5. 遍历结束后,如果 total_tank 大于等于 0,说明有解,返回 starting_station,否则返回 -1。

Python 示例

def canCompleteCircuit(gas, cost):
    total_tank, curr_tank = 0, 0
    starting_station = 0
    for i in range(len(gas)):
        total_tank += gas[i] - cost[i]
        curr_tank += gas[i] - cost[i]
        if curr_tank < 0:
            starting_station = i + 1
            curr_tank = 0
    return starting_station if total_tank >= 0 else -1
# Example usage
gas = [1, 2, 3, 4, 5]
cost = [3, 4, 5, 1, 2]
print(canCompleteCircuit(gas, cost))  # Output: 3
gas = [2, 3, 4]
cost = [3, 4, 3]
print(canCompleteCircuit(gas, cost))  # Output: -1

算法分析

  • 时间复杂度:O(N),其中 N 是加油站的数量。只需遍历一次所有的加油站。
  • 空间复杂度:O(1),只使用了常数级别的额外空间。

算法图解与说明

考虑 gas = [1, 2, 3, 4, 5], cost = [3, 4, 5, 1, 2]
总油量 total_tank = 0, 当前油量 curr_tank = 0, 起始站点 starting_station = 0
遍历每个加油站:
站点0: total_tank = -2, curr_tank = -2 (curr_tank < 0, 更新起始站点为1, curr_tank = 0)
站点1: total_tank = -4, curr_tank = -2 (curr_tank < 0, 更新起始站点为2, curr_tank = 0)
站点2: total_tank = -6, curr_tank = -2 (curr_tank < 0, 更新起始站点为3, curr_tank = 0)
站点3: total_tank = -3, curr_tank = 3 (curr_tank >= 0, 继续)
站点4: total_tank = 0, curr_tank = 4 (curr_tank >= 0, 继续)
总油量 total_tank >= 0,因此可以完成环路,返回起始站点3。

这种方法与方法一的核心思想类似,但通过使用前缀和的概念更加简洁地实现了解决方案。核心在于每次从当前油量不足的地方重新开始计算起点,并最终判断总油量是否满足条件。

🌹🌹如果觉得这篇文对你有帮助的话,记得一键三连关注、赞👍🏻、收藏是对作者最大的鼓励,非常感谢 ❥(^_-)

❤️❤️作者知识有限,如有错误,请各位大佬评论区批评指正,不胜感激❥(^_-)

欢迎关注微信公众号 数据分析螺丝钉

相关文章
|
2月前
|
机器学习/深度学习 算法 数据挖掘
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构。本文介绍了K-means算法的基本原理,包括初始化、数据点分配与簇中心更新等步骤,以及如何在Python中实现该算法,最后讨论了其优缺点及应用场景。
152 4
|
3月前
|
存储 算法 Java
解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用
在Java中,Set接口以其独特的“无重复”特性脱颖而出。本文通过解析HashSet的工作原理,揭示Set如何利用哈希算法和equals()方法确保元素唯一性,并通过示例代码展示了其“无重复”特性的具体应用。
69 3
|
10天前
|
机器学习/深度学习 人工智能 算法
机器学习算法的优化与改进:提升模型性能的策略与方法
机器学习算法的优化与改进:提升模型性能的策略与方法
100 13
机器学习算法的优化与改进:提升模型性能的策略与方法
|
19天前
|
算法 容器
【算法】——双指针算法合集(力扣)
移动零,复写零,快乐数,盛最多水的容器,有效三角形的个数,和为s的两个数(查找总价格为目标值的两个商品 ),三数之和,四数之和
|
2月前
|
存储 算法 安全
SnowflakeIdGenerator-雪花算法id生成方法
SnowflakeIdGenerator-雪花算法id生成方法
34 1
|
2月前
|
存储 算法 Java
leetcode算法题-有效的括号(简单)
【11月更文挑战第5天】本文介绍了 LeetCode 上“有效的括号”这道题的解法。题目要求判断一个只包含括号字符的字符串是否有效。有效字符串需满足左括号必须用相同类型的右括号闭合,并且左括号必须以正确的顺序闭合。解题思路是使用栈数据结构,遍历字符串时将左括号压入栈中,遇到右括号时检查栈顶元素是否匹配。最后根据栈是否为空来判断字符串中的括号是否有效。示例代码包括 Python 和 Java 版本。
|
2月前
|
JSON 算法 数据挖掘
基于图论算法有向图PageRank与无向图Louvain算法构建指令的方式方法 用于支撑qwen agent中的统计相关组件
利用图序列进行数据解读,主要包括节点序列分析、边序列分析以及结合节点和边序列的综合分析。节点序列分析涉及节点度分析(如入度、出度、度中心性)、节点属性分析(如品牌、价格等属性的分布与聚类)、节点标签分析(如不同标签的分布及标签间的关联)。边序列分析则关注边的权重分析(如关联强度)、边的类型分析(如管理、协作等关系)及路径分析(如最短路径计算)。结合节点和边序列的分析,如子图挖掘和图的动态分析,可以帮助深入理解图的结构和功能。例如,通过子图挖掘可以发现具有特定结构的子图,而图的动态分析则能揭示图随时间的变化趋势。这些分析方法结合使用,能够从多个角度全面解读图谱数据,为决策提供有力支持。
119 0
|
3月前
|
算法
每日一道算法题(Leetcode 20)
每日一道算法题(Leetcode 20)
38 2
|
3月前
|
算法 索引
HashMap扩容时的rehash方法中(e.hash & oldCap) == 0算法推导
HashMap在扩容时,会创建一个新数组,并将旧数组中的数据迁移过去。通过(e.hash & oldCap)是否等于0,数据被巧妙地分为两类:一类保持原有索引位置,另一类索引位置增加旧数组长度。此过程确保了数据均匀分布,提高了查询效率。
59 2
|
3月前
|
程序员 C语言
【C语言】LeetCode(力扣)上经典题目
【C语言】LeetCode(力扣)上经典题目