美文网首页
leetcode134gas-station 2020-11-1

leetcode134gas-station 2020-11-1

作者: 9_SooHyun | 来源:发表于2020-11-18 22:25 被阅读0次

leetcode134. 加油站

在一条环路上有 N 个加油站,其中第 i 个加油站有汽油 gas[i] 升。从第 i 个加油站开往第 i+1 个加油站需要消耗汽油 cost[i] 升。你从其中的一个加油站出发,开始时油箱为空。

如果你可以绕环路行驶一周,则返回出发时加油站的编号,否则返回 -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[i]汽油,并需要消耗cost[i]汽油到达下一站,必须保证到达下一站时存油非负。因此,可将gas[i]与cost[i]做差得到一个数组delta,例子中对应的delta为[-2,-2,-2,3,3]。因为初始汽油量为0,那么问题转化为,我们需要在delta中找到一个起点,保证从起点出发的任一路段和非负

解法1:
暴力模拟
对delta的每个位置,模拟走完一个环路。对于每一个起点,如果过程中出现负数和的情况,则从该起点出发不可环行一圈

class Solution:
    def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
        l = len(gas)
        delta = [gas[i]-cost[i] for i in range(l)]

        for i in range(l):
            # i位置为环路起点
            temp_delta = delta[i:] + delta[:i]
            total = 0
            # 检查temp_delta每一段的和是否为负
            for j in range(l):
                total += temp_delta[j]
                if total < 0:
                    break
            else:
                return i
        return -1

解法2:
在暴力模拟的基础上优化
暴力模拟需要check delta每一个位置为起点的情况,实际上不需要。假设站点0到站点k一路都正常,但到达不了站点k+1,这时如果我们再尝试区间[1, k]的站点为起点就多余了——从0开始都到不了k+1,从中间任意的站点 i 更加到不了k+1,因为少了 0-i 路段的汽油存储
因此,站点s为起点,如果发现站点k无法到达,起点应该重新定为k+1,而不是s+1,因为从[s, k]中的任一站点出发都无法到达k
对于delta而言,当序列和开始为负时,从下一位置重新计算序列和

class Solution:
    def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
        # 汽车行驶若干站点后gas < 0,则从下一站点重新出发
        l = len(gas)
        delta = [gas[i] - cost[i] for i in range(l)]
        i = 0
        while i < l:
            cur_gas = 0
            for j in range(l):
                cur_gas += delta[(i+j) % l]
                # 汽车行驶若干站点后gas < 0,则从下一站点重新出发
                if cur_gas < 0:
                    i = i + j + 1
                    break
            else:
                return i
        return -1

解法3:
if sum(gas) >= sum(cost),那么必然可以从某一站出发完成环行
互为充要:sum(gas) >= sum(cost) <=> 可以从某一站出发完成环行

下面证明 sum(gas) >= sum(cost) => 可以从某一站出发完成环行

反证法:
假设 sum(gas) >= sum(cost) ,则从任意一站出发都不能完成环行;
这里我们假定站点0不可达站点k,那么0-k这一段内有sum(sub_gas) < sum(sub_cost),且这一段内的任意一点都不可作为起点,新的尝试起点为站点k+1,而站点k+1又不可达站点kk,那么k+1-kk这一段又有sum(sub_gas) < sum(sub_cost),且段内的任意一点都不可作为起点——于是,每一段都有sum(sub_gas) < sum(sub_cost),加起来就得到sum(gas) < sum(cost) ,与sum(gas) >= sum(cost) 矛盾
因此,sum(gas) >= sum(cost) => 可以从某一站出发完成环行
可参考https://leetcode-cn.com/problems/gas-station/solution/shou-hua-tu-jie-liang-ge-guan-jian-jie-lun-de-jian/

也可以正向理解,如果sum(gas) >= sum(cost) ,那么我总可以贪心地找到一个起点,从那里开始疯狂存油,从而保证后面的消耗

即 sum(delta) >= 0 => 可以从某一站出发完成环行,这样问题就简单很多了

class Solution:
    def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
        l = len(gas)
        delta = [gas[i]-cost[i] for i in range(l)]
        
        # 计算sum(delta)
        total = 0
        # 计算当前油量
        cur = 0
        start_index = 0
        for i in range(l):
            cur += delta[i]
            total += delta[i]
            if cur < 0:
                cur = 0
                # 更新起点
                start_index = i + 1
        if total >= 0:
            return start_index
        return -1

相关文章

  • leetcode134gas-station 2020-11-1

    leetcode134. 加油站[https://leetcode-cn.com/problems/gas-sta...

  • Date对象

    1、创建日期 1)new Date() 返回系统当前日期和时间 2)new Date(‘2020-11-1 12:...

  • 2020-11-1

    没有不可治愈的伤痛,没有不能结束的沉沦。所有失去的,会以另一种方式归来。很多时候,很多事情,走不向希望的结局,错的...

  • 2020-11-1

    我对大宝说:“姥姥要回来了。”大宝问:“yi小姨也一起回来吗?”我答:“小姨得上班,没空!”大宝接着说:“那姥姥可...

  • 2020-11-1

    所谓智囊,就是见解比别人高,看得比别人远,顺境中能看到危机,逆境中能找到机会,胸藏百万兵,在帷幄之中可以运筹千里。...

  • 2020-11-1

    比赛总结 今天这两场球,我们的对手都不强,再者,孩子们的整体能力是有提升的,打这样的比赛,没有压力,我希望孩子们能...

  • 2020-11-1

    醒来后已经9:30了,洗了洗衣服, 和实验室的小伙伴一起吃了火锅,逛了超市,下午和吴一起打了球,看了电影。不过回学...

  • 2020-11-1

    刚步入大学的心得体会 时间就像海绵里的水,一不小心就溜走了,转眼间大一第一学期的学习生活已接近尾声,在这一学期里经...

  • 2020-11-1

    Y 小姐买了个羊毛大衣,帽子上有一圈毛毛。 不带帽子的时候觉得还挺可爱,带上帽子就是一只熊。 Y 小姐问 Y 先生...

  • 鼎然之语2020-11-1

    鼎然之语2020-11-1 ([拥抱][拥抱][拥抱])世人怕死并非因为有个“我”,而是不识得死亡真相,因为不识得...

网友评论

      本文标题:leetcode134gas-station 2020-11-1

      本文链接:https://www.haomeiwen.com/subject/wukhiktx.html