代码随想录算法训练营第二十七天 | 贪心算法理论基础、455.分发饼干、376. 摆动序列、53. 最大子序和

一、贪心算法理论基础

文章讲解:代码随想录 (programmercarl.com)——贪心算法理论基础

视频讲解:贪心算法理论基础!_哔哩哔哩_bilibili

什么是贪心:局部最优推出全局最优。

二、455.分发饼干

题目链接:455. 分发饼干 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)——455.分发饼干
视频讲解:贪心算法,你想先喂哪个小孩?| LeetCode:455.分发饼干_哔哩哔哩_bilibili

思路:局部最优——每次找到一个大饼干,满足胃口大的小号;全局最优——喂饱最多的小孩。

"""
优先用大饼干喂饱大小孩
"""
class Solution:
    def findContentChildren(self, g: List[int], s: List[int]) -> int:
        # 对饼干和小孩排序
        g.sort()
        s.sort()

        # 初始化喂饱小孩数
        result = 0

        # 初始化饼干下标
        index = len(s) - 1

        # 从大到小遍历,优先喂饱胃口大的小孩
        # for循环一定先遍历胃口
        for i in range(len(g) - 1, -1, -1):
            # 饼干索引合法且饼干尺寸比小孩胃口大
            # index >= 0 一定要写在 s[index] >= g[i]前面,否则可能出现异常
            if index >= 0 and s[index] >= g[i]:
                # 喂饱小孩数量+1
                result += 1
                # 饼干索引往前一位
                index -= 1

        return result
"""
小饼干优先喂饱小小孩
"""
class Solution:
    def findContentChildren(self, g: List[int], s: List[int]) -> int:
        # 对饼干和小孩排序
        g.sort()
        s.sort()

        # 初始化喂饱小孩数,即小孩的位置索引
        index = 0

        # 从大到小遍历,优先喂饱胃口大的小孩
        # for循环遍历饼干
        for i in range(len(s)):
            # 如果小孩索引合法且胃口小于等于饼干大小,喂下一个小孩,否则找下一块饼干能否满足该小孩胃口
            if index < len(g) and g[index] <= s[i]:
                index += 1

        return index

三、376. 摆动序列

题目链接:376. 摆动序列 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)——376. 摆动序列
视频讲解:贪心算法,寻找摆动有细节!| LeetCode:376.摆动序列_哔哩哔哩_bilibili

思路:局部最优——单调坡上的元素都删掉,遇到摆动做 result += 1,遇到坡上的值不变。
平坡处理:如果遇到平坡,光删左边的删除。
首尾元素:首元素默认prediff有个1,最后一个不遍历,result从1开始。

class Solution:
    def wiggleMaxLength(self, nums: List[int]) -> int:
        # 如果只有1个元素,则序列长度为1
        if len(nums) <= 1:
            return len(nums)

        prediff = 0        # 初始化与前一个元素差值
        curdiff = 0        # 初始化与后一个元素差值
        result = 1         # 初始化序列长度为1

        # 循环范围 len(nums) - 1 因为,不算最后一个元素了
        for i in range(len(nums) - 1):
            # 计算后一个元素差值
            curdiff = nums[i + 1] - nums[i]
            # 如果遇到峰值
            if (prediff >= 0 and curdiff < 0) or (prediff <= 0 and curdiff > 0):
                result += 1
                # 写道if里为了处理单调有平坡的情况,即只有发生摆动时更新prediff
                prediff = curdiff
        return result

四、53. 最大子序和

题目链接:53. 最大子数组和 - 力扣(LeetCode)
文章讲解:代码随想录 (programmercarl.com)——53. 最大子序和
视频讲解:贪心算法的巧妙需要慢慢体会!LeetCode:53. 最大子序和_哔哩哔哩_bilibili

思路:局部最优——当求解为负数时直接抛弃当前和,从下一个正数开始重新规定起始位置,并用result数组记录下局部最优。

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        # 因为要求最大值,所以初始化为最小值
        result = float("-inf")

        count = 0

        for i in range(len(nums)):
            # 累加数字
            count += nums[i]
            # 取最大值
            if count > result:
                result = count
            
            # 重置最大和起始位置
            if count <= 0:
                count = 0
            
        return result
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值