最佳加油站选择算法:解决环路加油问题的两种高效方法|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。

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

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

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

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

相关文章
|
7月前
|
存储 编解码 算法
【多光谱滤波器阵列设计的最优球体填充】使用MSFA设计方法进行各种重建算法时,图像质量可以提高至多2 dB,并在光谱相似性方面实现了显著提升(Matlab代码实现)
【多光谱滤波器阵列设计的最优球体填充】使用MSFA设计方法进行各种重建算法时,图像质量可以提高至多2 dB,并在光谱相似性方面实现了显著提升(Matlab代码实现)
239 6
|
7月前
|
机器学习/深度学习 算法 调度
14种智能算法优化BP神经网络(14种方法)实现数据预测分类研究(Matlab代码实现)
14种智能算法优化BP神经网络(14种方法)实现数据预测分类研究(Matlab代码实现)
566 0
|
8月前
|
机器学习/深度学习 数据采集 传感器
具有多种最大功率点跟踪(MPPT)方法的光伏发电系统(P&O-增量法-人工神经网络-模糊逻辑控制-粒子群优化)之使用粒子群算法的最大功率点追踪(MPPT)(Simulink仿真实现)
具有多种最大功率点跟踪(MPPT)方法的光伏发电系统(P&O-增量法-人工神经网络-模糊逻辑控制-粒子群优化)之使用粒子群算法的最大功率点追踪(MPPT)(Simulink仿真实现)
563 0
|
6月前
|
机器学习/深度学习 数据采集 负载均衡
结合多种启发式解码方法的混合多目标进化算法,用于解决带工人约束的混合流水车间调度问题(Matlab代码实现)
结合多种启发式解码方法的混合多目标进化算法,用于解决带工人约束的混合流水车间调度问题(Matlab代码实现)
318 0
|
6月前
|
存储 人工智能 算法
从零掌握贪心算法Java版:LeetCode 10题实战解析(上)
在算法世界里,有一种思想如同生活中的"见好就收"——每次做出当前看来最优的选择,寄希望于通过局部最优达成全局最优。这种思想就是贪心算法,它以其简洁高效的特点,成为解决最优问题的利器。今天我们就来系统学习贪心算法的核心思想,并通过10道LeetCode经典题目实战演练,带你掌握这种"步步为营"的解题思维。
|
6月前
|
机器学习/深度学习 算法 物联网
基于遗传方法的动态多目标优化算法
基于遗传方法的动态多目标优化算法
|
机器学习/深度学习 算法 数据挖掘
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构
K-means聚类算法是机器学习中常用的一种聚类方法,通过将数据集划分为K个簇来简化数据结构。本文介绍了K-means算法的基本原理,包括初始化、数据点分配与簇中心更新等步骤,以及如何在Python中实现该算法,最后讨论了其优缺点及应用场景。
1596 6
|
11月前
|
Go 开发者 索引
【LeetCode 热题100】路径与祖先:二叉树中的深度追踪技巧(力扣33 / 81/ 153/154)(Go语言版)
本文深入探讨了LeetCode中四道关于「搜索旋转排序数组」的经典题目,涵盖了无重复和有重复元素的情况。通过二分查找的变形应用,文章详细解析了每道题的解题思路和Go语言实现代码。关键点包括判断有序区间、处理重复元素以及如何缩小搜索范围。文章还总结了各题的异同,并推荐了类似题目,帮助读者全面掌握二分查找在旋转数组中的应用。无论是初学者还是有经验的开发者,都能从中获得实用的解题技巧和代码实现方法。
473 14
|
10月前
|
Go
【LeetCode 热题100】DP 实战进阶:最长递增子序列、乘积最大子数组、分割等和子集(力扣300 / 152/ 416 )(Go语言版)
本文深入解析三道经典的动态规划问题:**最长递增子序列(LIS)**、**乘积最大子数组** 和 **分割等和子集**。 - **300. LIS** 通过 `dp[i]` 表示以第 `i` 个元素结尾的最长递增子序列长度,支持 O(n²) 动态规划与 O(n log n) 的二分优化。 - **152. 乘积最大子数组** 利用正负数特性,同时维护最大值与最小值的状态转移方程。 - **416. 分割等和子集** 转化为 0-1 背包问题,通过布尔型 DP 实现子集和判断。 总结对比了三题的状态定义与解法技巧,并延伸至相关变种问题,助你掌握动态规划的核心思想与灵活应用!
409 1