加油站-(贪心算法)

题目描述

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

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

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

示例 1:

复制代码
输入: gas = [1,2,3,4,5], cost = [3,4,5,1,2]
输出: 3
解释:
从 3 号加油站(索引为 3 处)出发,可获得 4 升汽油。此时油箱有 = 0 + 4 = 4 升汽油
开往 4 号加油站,此时油箱有 4 - 1 + 5 = 8 升汽油
开往 0 号加油站,此时油箱有 8 - 2 + 1 = 7 升汽油
开往 1 号加油站,此时油箱有 7 - 3 + 2 = 6 升汽油
开往 2 号加油站,此时油箱有 6 - 4 + 3 = 5 升汽油
开往 3 号加油站,你需要消耗 5 升汽油,正好足够你返回到 3 号加油站。
因此,3 可为起始索引。

思路分析

首先,我们要判断一个加油站是否能到下一个加油站,需要看gas[j]>cost[j],所以我们关注的点应该是gas[j]-cost[j]。所以我们先计算出经过每个站点,油箱是增加油量还是减少油量。remainder[j]=gas[j]-cost[j]。

然后我们判断,什么时候汽车无法绕一圈呢,也就是汽油不够呢。简单举几个例子就知道,只有在remainder[j]的总和是负数的时候才会出现。比如说remianer=[3,-1,0,-1,0],总和是1,即使大部分是0或者是负数,但还是能找到个起点,然后绕一圈。

最后的重点就是,找出这唯一的起点(题目中说解唯一)。

思路一:联想 最大子数组和

一开始我想到了一个类似的题目:最大子数组和,可以用到贪心、前缀和或者动态规划三种思路解决。但是这个题目求的是最大子数组和,但是本题求的是索引。改写起来的复杂度为O(2N)。

python 复制代码
class Solution:
    def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
        column = len(gas)
        remainder = [0] * column
        for i in range(column):  #计算经过每个加油站油箱的增量
            remainder[i] = gas[i] - cost[i]
        if sum(remainder) < 0:
            return -1
        max_value = 0
        result = 0
        index = 0
        max_index = 0
        flag = True
        #这里是2*column,因为要考虑是环路,也就是循环数组
        for i in range(2*column):
            if flag: #是否要记录当前起始下标
                index = i%column
                flag = False
            result += remainder[i%column]
            if result < 0: #从当前下标无法绕一圈
                result = 0
                # 再次开始记录下标
                flag = True
            if result > max_value: #记录这个可能的索引
                max_value = result
                max_index = index
        return max_index

思路二:贪心算法

看到leetcode官方解,只需遍历一遍即可找出起始下标。所以对上面的代码修改,如果当前从第index个加油站出发,到第right个加油站时油箱为负数时,那么即使从index-right之间的任意加油站出发,同样无法绕过第right个加油站。比如说你选了第x个加油站(index<x<right),其实从index到x之间油箱剩余的油量肯定是大于等于0的,不然不可能到达第x个加油站。所以从index都到不了right,更别说中间的其他加油站出发了。

所以当遇到油量为负数时,我们直接可以跳过起始和末尾这些加油站,从right+1的加油站开始重新遍历结算。

python 复制代码
class Solution:
    def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
        column = len(gas)
        remainder = [0] * column
        for i in range(column):
            remainder[i] = gas[i] - cost[i]
        if sum(remainder) < 0:
            return -1
        # 如果总和不为负数,那么一定可以找到从一个点开始,能遍历全部
        qianzhui = 0
        index = 0

        while index < column:
            for j in range(index, column):
                qianzhui += remainder[j]
                if qianzhui < 0:  # 汽油不够了
                    qianzhui = 0
                    index = j+1
                    break
            else:
                return index
相关推荐
郝学胜-神的一滴8 小时前
[简化版 GAMES 101] 计算机图形学 04:二维变换上
c++·算法·unity·godot·图形渲染·unreal engine·cesium
ZC跨境爬虫8 小时前
海南大学交友平台开发实战day7(实现核心匹配算法+解决JSON请求报错问题)
前端·python·算法·html·json
计算机安禾8 小时前
【数据结构与算法】第41篇:图论(五):拓扑排序与关键路径
c语言·数据结构·c++·算法·图论·visual studio
Q741_1478 小时前
每日一题 力扣 1320. 二指输入的的最小距离 动态规划 C++ 题解
c++·算法·leetcode·动态规划
wfbcg8 小时前
每日算法练习:LeetCode 76. 最小覆盖子串 ✅
算法·leetcode·职场和发展
Wect8 小时前
LeetCode 149. 直线上最多的点数:题解深度剖析
前端·算法·typescript
qianpeng8978 小时前
运动声源的到达结构仿真
算法
费曼学习法8 小时前
线段树:区间查询的"终极武器",一文看透高效范围统计
算法
wayz119 小时前
Day 2:线性回归原理与正则化
算法·机器学习·数据分析·回归·线性回归
QQ676580089 小时前
基于yolo26算法的水下目标检测图像数据集 海洋生物识别 海胆识别 海龟识别数据集 海洋生物监测与保护工作 潜水作业安全辅助系 水下环境感知第10408期
算法·目标检测·水下目标检测·海洋生物识别·海胆 海龟识别·海洋生物监测与保护工作·潜水作业安全辅助 水下环境感知