Leetcode每日一题2020.11.18第134题:加油站

题目描述

在这里插入图片描述

示例

在这里插入图片描述
在这里插入图片描述

思路、算法及代码实现

首先,我们看完题后,想到的方法一定是暴力遍历法,即从头到尾遍历每个加油站,并检查以该加油站为起点,最终能否行驶一周。
但其实如果我们发现一个逻辑上的小性质的话,就可以只遍历一次。
我们在推理这个性质的过程中,先不考虑“油不能为负数”这个限制,
设left[i]=gas[i]-cost[i],当left[i]越小,说明消耗越多。我们从示例2可以看出,当left[i]<0时,说明没有足够的油从第i个点到第i+1个点,所以left<0的点都不能作为起点。此时可以从最后一个left<0的点的后面那一点开始作为起点,并且要求满足后面的总left要能够补偿前面欠下的负的总left,才能保证走完一周,即总油数一定要大于等于总消耗,本题才能有解。因为从0跑到最后一个left<0的位置,总left最小,即这一段的消耗是整条链上最大的,所以从最后一个left<0的点的后面那个点开始作为起点的话,最终剩下的油一定是最多的,所以只需要遍历一次找到最后一个left<0的点即可。

class Solution:
    def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
        left = [gas[i] - cost[i] for i in range(len(cost))]
        minValue = 999
        minIndex = 0

        sumValue = 0  # 总油数-总消耗
        # 一举两得:既可以找到最后一个left<0的点,又可以算得(总油数-总消耗)
        for j, l in enumerate(left):
            sumValue += l
            if sumValue < minValue:
                minValue = sumValue
                minIndex = j

        if sumValue < 0:
            return -1
        else:
            return (minIndex + 1) % len(cost)  # 因为是一个圆圈,所以要求余数得到序号
			

在这里插入图片描述

小经验

当要“求最后一个负数”时,转化为“和最小”更巧妙;同理,要“求最后一个正数”时,转化为“和最大”更巧妙。

猜你喜欢

转载自blog.csdn.net/m0_51210480/article/details/111830351
今日推荐