加油站问题的题解与分析——循环队列+合并

本文介绍了如何使用循环队列和元素合并的方法解决加油站问题。通过初始化和遍历循环队列,分析加油站的正负性质,找到能使汽车绕行一周的起点加油站。以给定示例为例,详细解释了算法的实现过程。
摘要由CSDN通过智能技术生成

1. 题目描述

  • 问题来源及详细描述:https://leetcode-cn.com/problems/gas-station/

  • 描述:汽车的初始油量为0,油箱容量无限大,判断是否能够从某一加油站出发,绕环路行驶一周。
    输入:每个加油站的油量gas,每个加油站前往下一个加油站的耗油量cost,cost[end]表示最后一个加油站前往第一个加油站的耗油量。
    输出:满足条件的起始加油站编号 or -1

  • 示例说明:
    如下图所示,每个圆圈代表一个加油站,圆圈内的数字为加油站的编号,箭头方向为绕行方向。加油站上方的数字表示当前当油站的油量cost[i],加油站之间的数字表示从上一个加油站前往下一个加油站的耗油量cost[i]。
    在这里插入图片描述
    输入:gas=[1, 2, 3, 4, 5], cost=[3, 4, 5, 1, 2]
    输出:3(汽车可从3号加油站出发绕行一周)
    分析:如下表所示,汽车从3号加油站出发,沿着3→4→0→1→2→3的顺序可绕行一周返回出发时的加油站。

    加油站编号(i) 加油站油量(gas) 前往下一个加油站的耗油量(cost) 到达当前加油站时汽车剩余油量 离开当前加油站时汽车剩余油量
    0 1 3 8-2=6 6+1=7
    1 2 4 7-3=4 4+2=6
    2 3 5 6-4=2 2+3=5
    3 4 1 0(出发)→5-5=0(结束) 0+4=4(出发)
    4 5 2 4-1=3 3+5=8
  • 注意:

    1. 汽车移动过程中(到达加油站和离开加油站时),油箱的油量始终为非负数
    2. 从某个车站前往下一个车站的相对油量(gas[i]-cost[i])的值取决于输入;
    3. 题目可以转换为寻找一个可行的起始加油站,使得油箱剩余油量+相对油量在每一个车站都为非负数。

2. 解题思路—循环队列

  • 关键方法:循环队列+元素合并
  • 综合分析:
    1. 循环队列在初始情况下记录汽车在加油站的相对油量,更新过程中记录加油站的累计情况;
    2. 根据相邻加油站的相对油量判断加油站的性质,根据性质进行累加,逐渐减少循环队列中的元素。
      当加油站的相对油量<0时,即汽车无法以该加油站为起点前往下一个加油站,称该加油站为负加油站
      当加油站的相对油量>0时,即汽车可能以该加油站为起点前往下一个加油站,称该加油站为正加油站

2.1 初始化循环队列

  • 分析:
    循环队列可以达到题目要求的最后一个加油站的下一个位置是第一个加油站的效果。
    通过合并循环队列中相同性质和不同性质的加油站,判断汽车是否能够绕行一周以及记录绕行起点。
class Solution {
   
public:
	int canCompleteCircuit(vector<int>& gas, vector<int>& cost) {
   	//输入油量信息gas和前往下一站的油耗信息cost
		queue<pair<int, int>> q;	//创建循环队列,队列中每个元素保存两个值
      	//初始化时,每个元素中保存(相对油量,当前加油站的编号),相对油量=当前油量-前往下一站的油耗
		for (int i = 0; i < gas.size(); i++) q.push(pair<int, int>(gas[i] - cost[i], i));
      
      	//初始化循环队列遍历过程的标志变量
		int sum = 0, pos = -1;	//sum记录多个相邻的加油站的相对油量的累加值,pos记录这些加油站中第一个加油站的编号
		bool init = false;		//init记录是否完成一次累加
      
      	//模块:遍历和修改循环队列

		return pos;				//输出可行的加油站起点编号 or -1
	}
};

2.2 遍历和修改循环队列

  • 分析:主要是循环队列中元素的合并
    • 当加油站为相同性质的加油站时,可以直接合并;
      若相邻加油站( g 1 , g 2 , . . . , g n g_1, g_2, ...,g_n
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值