首页 > 编程语言 >吴师兄学算法day08 贪心 134. 加油站

吴师兄学算法day08 贪心 134. 加油站

时间:2024-01-19 17:37:09浏览次数:32  
标签:__ day08 int List gas 加油站 cost 134 贪心

题目:134. 加油站

理解难点:

  • 理解比较难,
  • 就是遍历1遍,尽可能找局部满足要求的。如果总油耗满足要求。那局部油耗找的出发点就是对的。
  • 遍历的时候,因为答案唯一,要么就满足要求,要么不满足要求。而<0 证明之前的都不满足要求,满足要求的一定在后面。
  • 这题还是个环,环这里有点没太理解。环也是线的一种?

画图理解中:

我的代码:

class Solution:
    def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
        cur_sum = 0
        total_sum = 0
        start = 0
        for i in range(len(gas)):
            # 每次计算油耗和总油耗
            cur_sum += gas[i] - cost[i]
            total_sum += gas[i] - cost[i]
            if cur_sum < 0:
                # 重新出发
                cur_sum = 0  # 油耗归零
                start = i + 1   # 重新出发
        # 现在start 存放的是尽可能满足要求的
        # 如果总油耗不为负数,则start是满足要求的
        if total_sum<0:
            return -1
        return start

老师的代码:

from typing import List


class Solution:
    def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
        # 获取加油站的数量
        n = len(gas)

        # 一开始,默认汽车储备的汽油数量为 0
        remainGas = 0

        # 需要统计一下,所有加油站的汽油总量能否支持汽车跑完所有的路程
        for i in range(n):
            remainGas += gas[i] - cost[i]

        # 如果发现加油站的汽油总量小于所有的路程需要消耗的汽油总量
        # 即汽车最终油箱汽油为负,那无论选择在哪出发,都不可能绕环路行驶一周
        print(remainGas)
        if remainGas < 0:
            return -1

        # 如果发现加油站的汽油总量大于或者等于所有的路程需要消耗的汽油总量
        # 那么可以绕环路行驶一周,接下来去寻找出发位置

        # 一开始,默认汽车此时储备的汽油数量为 0
        currentGas = 0

        # 一开始,默认汽车出发位置在索引为 0 的加油站
        i = 0

        # index 表示最终选择的出发点,默认为 0
        index = 0

        # 依次遍历每个加油站,在遍历的过程中,会执行一些【跳跃操作】
        while i < n:

            # 汽车在 i 号加油站加了 gas[i]
            # 开到 i + 1 号加油站消耗了 cost[i] 的汽油
            currentGas += gas[i] - cost[i]

            # 如果发现油箱里面的汽油是非负数
            # 即汽车可以开到  j 号加油站,j >= i + 1,那么就让汽车继续尝试往前开
            # 寻找出从 i 号加油站出发到最远的加油站的位置 j ,在这期间汽车是会从中间的加油站加油的
            if currentGas >= 0:
                print("此时油量为正数:", currentGas, "此时的i:", i)
                i += 1

            # 如果发现油箱里面的汽油是负数
            # 意味着汽车无法从 i 号加油站开到 j 号加油站,同时也意味着无法从 i + 1 号加油站开到 j 号加油站
            # 那么就直接尝试让汽车从 j 号加油站开始重新出发
            else:
                print("此时为负数:", currentGas)
                # 重新初始化汽车油箱油量
                currentGas = 0

                # 最终选择的出发点为 j 号加油站
                index = i + 1
                print("重新选择的加油站", index)

                # 开始出发
                i += 1
        print("最后邮箱:", currentGas)
        # 最终找到了合适的出发点
        return index


if __name__ == '__main__':
    obj = Solution()
    gas = [5, 2, 2, 7, 5, 5, 6, 1]
    cost = [3, 4, 5, 6, 7, 2, 1, 5]
    # diff = [2,-2,-3,1,-2,3,5,-4]
    print(obj.canCompleteCircuit(gas, cost))

卡尔的写法:

from typing import List


class Solution:
    def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
        curSum = 0  # 当前累计的剩余油量
        totalSum = 0  # 总剩余油量
        start = 0  # 起始位置

        for i in range(len(gas)):
            curSum += gas[i] - cost[i]
            totalSum += gas[i] - cost[i]

            if curSum < 0:  # 当前累计剩余油量curSum小于0
                start = i + 1  # 起始位置更新为i+1
                curSum = 0  # curSum重新从0开始累计

        # if totalSum < 0:
        #     return -1  # 总剩余油量totalSum小于0,说明无法环绕一圈

        return start

if __name__ == '__main__':
    obj = Solution()
    gas = [5, 2, 2, 7, 5, 5, 6, 1]
    cost = [3, 4, 5, 6, 7, 2, 1, 5]
    # diff = [2,-2,-3,1,-2,3,5,-4]
    print(obj.canCompleteCircuit(gas, cost))

github上的代码:

class Solution:
  def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
    ans = 0
    net = 0
    summ = 0

    # Try to start from each index.
    for i in range(len(gas)):
      net += gas[i] - cost[i]
      summ += gas[i] - cost[i]
      if summ < 0:
        summ = 0
        ans = i + 1  # Start from the next index.

    return -1 if net < 0 else ans

总结:

  • 不行就抄一遍。
  • 多画图,多理解。
  • 不完全理解也没关系,边背边理解。
  • 背诵中理解!
  • 加油!!!

参考:

吴师兄:https://r07na4yqwor.feishu.cn/docx/KJ0OduxXfoGwMcxUs00cBX4onyr

卡尔代码及题解

github 大神代码:https://walkccc.me/LeetCode/problems/0134/#__tabbed_1_3

标签:__,day08,int,List,gas,加油站,cost,134,贪心
From: https://www.cnblogs.com/liqi175/p/17975158

相关文章

  • CF1340F Nastya and CBS
    更好的阅读体验CF1340FNastyaandCBS绷不住了,30min写完,虚空调试2h+/lh/lh。如果要准确做的话太困难了,考虑hash。多次区间询问,考虑线段树。一个区间如果内部合法,把内部能匹配的都匹配上,一定是左边一段右括号加上右边一段左括号。节点需要记录左边长度,右边长度和左右分别的......
  • 吴师兄学算法day08 贪心 LC455. 分发饼干
    题目:455. 分发饼干易错点:这两个变量名容易弄混s是饼干g是胃口图示:我的代码:classSolution:deffindContentChildren(self,g:List[int],s:List[int])->int:#对饼干s排序s.sort()#对孩子们的胃口g进行排序g.sort()......
  • 贪心算法题目2-力扣860
    在柠檬水摊上,每一杯柠檬水的售价为 5 美元。顾客排队购买你的产品,(按账单 bills 支付的顺序)一次购买一杯。每位顾客只买一杯柠檬水,然后向你付 5 美元、10 美元或 20 美元。你必须给每个顾客正确找零,也就是说净交易是每位顾客向你支付 5 美元。注意,一开始你手头没有任......
  • 贪心算法-题目3力扣53
    给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。子数组 是数组中的一个连续部分。输入:nums=[-2,1,-3,4,-1,2,1,-5,4]输出:6解释:连续子数组 [4,-1,2,1]的和最大,为 6。子数组 是数组中的一个连续部分。解题思路:从投......
  • 贪心算法-题目1力扣455(简单题)
    力扣455,给小朋友发饼干假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j]>=g[i],我们可以将这个饼干 j 分配......
  • day08-字典
    字典(Dict)是一种可变、无序的数据类型;那等等...我们回忆一下,字符串列表元祖是什么样的?字符串不可变,有序列表可变,有序元祖不可变,有序如何判断有序和无序呢,我首先确定在字符串、列表、元祖篇我们都讲到了切片取值,说明他们都是有顺序的,而字典是无序的,说明字典无法通过切片取值,......
  • 贪心国王游戏
    贪心耍杂技的牛国王游戏同款思路大部分贪心用的都是已经被证明过的知名的数学模型贪心得到的答案>=最优解贪心得到答案<=最优解#include<iostream>#include<algorithm>usingnamespacestd;//给pair<int,int>起个别名PIItypedefpair<int,int>P......
  • CF1914F Programming Competition 贪心原则的DP?
    终于理解了...希望写给小伙伴们,希望大伙可以理解。先确定贪心规则,即当最大子树不超过根子树减一的一半时,内部节点可以完全匹配。否则,可以先拿其他子树节点与最大子树内部节点匹配,子树内部再进行匹配。啥你说子树内部不够匹配怎么办?可以这么想,你这样都到匹配上限了,已经完全可以达......
  • 第 120 场双周赛(前缀和,双指针,树形dp+贪心)
     classSolution:deflargestPerimeter(self,nums:List[int])->int:nums.sort()n=len(nums)s=list(accumulate(nums))foriinrange(n-1,1,-1):ifnums[i]<s[i-1]:returnn......
  • [排序,贪心,置换环]洛谷P1327&&P8637,双倍经验
    前置知识:置换环,最小交换次数https://blog.csdn.net/yunxiaoqinghe/article/details/113153795?ops_request_misc=&request_id=&biz_id=102&utm_term=%E6%9C%80%E5%B0%91%E4%BB%BB%E6%84%8F%E4%BA%A4%E6%8D%A2%E6%8E%92%E5%BA%8F%E8%AF%81%E6%98%8E%E7%94%A8%E7%BD%AE%E6%8D......