代码随想录算法训练营第二十五天|134. 加油站、135. 分发糖果、860.柠檬水找零、406.根据身高重建队列

写代码的第二十五天
继续贪心!!gogogo!

134. 加油站

思路

贪心算法总让我有种脑子知道每次怎么计算,但是写不出来,也想不出贪心贪在哪里了,就只是觉得应该这么做。。。。。
本题中大家可以按照自己的计算方法一步一步模拟一下这个过程,然后会发现其实每次都是要计算每站剩余的油量,统计每一次的剩余油量然后累加计算,如果这个累加油量小于零那么就证明这个点之前的所有的点包括这个点都不满足走一圈的条件,从这个点之后的点继续向后遍历。
错误第一版:测试用例没通过,cursum在发现小于零的时候应该归零,因为从新开始的点开始遍历,累加和也要重新开始。

class Solution:
    def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
        start = 0
        cursum = 0
        for i in range(len(gas)):
            cursum += (gas[i]-cost[i])
            if cursum < 0:
                start = i + 1
        if cursum < 0:
            return -1
        return start

正确代码

class Solution:
    def canCompleteCircuit(self, gas: List[int], cost: List[int]) -> int:
        start = 0
        cursum = 0
        totalsum = 0
        for i in range(len(gas)):
            cursum += (gas[i]-cost[i])
            totalsum += (gas[i]-cost[i])
            if cursum < 0:
                start = i + 1
                cursum = 0
        if totalsum < 0:
            return -1
        return start

135. 分发糖果

思路

本题的要求是每个小孩最少一块糖,相邻的小孩分高的糖要更多,问怎么能用最少的糖果满足这个条件。可以分成两部分解决这个问题,从左向右和从右向左两个方向分别计算。初始化所有孩子的糖果都为1.
从左向右:如果右侧比左侧的分高,那么右侧应该在左侧的糖果的基础上加一;如果右侧小于等于左侧,那么右侧糖果数为1.
从右向左:在上述从左向右的基础上就是已经满足了右侧大于左侧的情况的糖果数量,现在要比较左侧比右侧大的时候的糖果数量,在上述糖果数量的基础上,如果左侧比右侧的糖果数量大,那么要在右侧糖果的基础上加一,需要注意一个问题如果这个时候的加一之后的值小于上一步计算之后的值,那么我们要保留最大的那个(只有保留最大的那个,才能满足左到右和右到左两部分);如果左侧小于等于右侧的糖果数量,此时不能设置左侧为1,如果设置为1,那么之前从左向右的计算就没有意义了,所以应该保持之前的到的值不变。
正确代码

class Solution:
    def candy(self, ratings: List[int]) -> int:
        candy = [1] * len(ratings)
        for i in range(len(ratings)):
            if i > 0 and ratings[i] > ratings[i-1]:
                candy[i] = candy[i-1] + 1
        for i in range(len(ratings)-2,-1,-1):
            if ratings[i] > ratings[i+1]:
                candy[i] = max(candy[i+1] + 1,candy[i])
        return sum(candy)

860.柠檬水找零

思路

题意只有5 10 20这三种情况的钱,所以根据这三种情况进行找零分析:
1、收到5的时候:直接收下,不用找零;
2、收到10的时候:如果有5,那么正常找零;如果没有5那么无法找零,失败;
3、收到20的时候:如果有一张10,一张5,那么正常找零;如果没有10,但是有三张5,也可以正常找零;如果不满足上面俩条件,那么失败。
(为什么要先判断有没有10,因为对于10来说只能对20进行找零,其他的时候没用,而5可以对10也可以对20找零,用处更广。)
正确代码

class Solution:
    def lemonadeChange(self, bills: List[int]) -> bool:
        five = 0
        ten = 0
        for i in range(len(bills)):
            if bills[i] == 5:
                five += 1
            elif bills[i] == 10:
                if five:
                    five -= 1
                    ten += 1
                else:
                    return False
            elif bills[i] == 20:
                if ten and five:
                    ten -= 1
                    five -= 1
                elif five >= 3:
                    five -= 3
                else:
                    return False
        return True

406.根据身高重建队列

思路

本题有两个维度h和k,首先要决定 先排哪个维度?
如果先排k:以这个为例people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]],按照从小到大的顺序people=[[7,0].[5,0],[7,1],[6,1],[5,2],[4,4]],在这个顺序的基础上排h,然后会发现排完k对排h没有任何帮助,还是要手动一点一点调(动手写一下就明白了,这次排序没起到任何作用),没有任何可以插入的规律。
如果先排h:以这个为例people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]],按照从大到小的顺序(因为二维数组中的数据代表的就是前面有k个大于等于h的数据,所以从大到小排更方便)people=[[7,0],[7,1],[6,1],[5,0],[5,2],[4,4]],在这个顺序的基础上排k,此时70和71都满足题条件,61不满足条件,但是按照我们的排序顺序将61插入到下标为1的位置就可以了,因为h的顺序是已经排完的,所以是在有序的基础上只要将前面比他大于等于的数字满足k就行,排序之后的顺序是70 61 71,在看50也不满足所以将50插入到下标为0的点就行了,排序之后的顺序是50 70 61 71,再看52,将其插入到下标为2的位置就行了,排序之后的顺序是50 60 52 61 71,最后是44也不满足条件,将44插入到下标为4的位置即可,50 60 52 61 44 71,与最后的输出结果一致。
正确代码:这个题对我来说代码难得部分在people = sorted(people, key=lambda x: (-x[0], x[1])),以及queue.insert(position,people[i])。语法要记住。
解释一下为什么是position = people[i][1],我们是按照下标位置插入的,看上面写的思路中比如44也不满足条件,将44插入到下标为4的位置即可,我们是按照k的位置进行插入的,所以i代表的是在people这个数组中的哪个数组需要插入进queue(比如【4,4】),1代表的是people数组中第i位数组中的下标为1的数字,这个数字才是我们要在queue中插入的位置(【4,4】中的第二个4)。

class Solution:
    def reconstructQueue(self, people: List[List[int]]) -> List[List[int]]:
        people = sorted(people, key=lambda x: (-x[0], x[1]))
        queue = []
        for i in range(len(people)):
            position = people[i][1]
            queue.insert(position,people[i])
        return queue
  • 12
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代码随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14训练营中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值