代码随想录学习Day 27

贪心算法理论基础

贪心的本质:通过每一阶段的局部最优推出全局最优。

思路:找局部最优,看能不能推出全局最优,并尝试举反例。

步骤:

  • 将问题分解为若干个子问题
  • 找出适合的贪心策略
  • 求解每一个子问题的最优解
  • 将局部最优解堆叠成全局最优

455.分发饼干

题目链接

讲解链接

首先想到的解法是先将s数组和g数组按照从小到大的顺序排序,然后用两个for循环来遍历两个数组,外层遍历g数组,内层遍历s数组,每次遇到满足gi < si的情况时就将result+1,然后将si置零代表这篇饼干已被使用过,并跳出当前层循环;若不满足则直接continue,查找下一片饼干。总体思路就是优先满足胃口小的孩子。

python 复制代码
class Solution:
    def findContentChildren(self, g: List[int], s: List[int]) -> int:
        s.sort()  # 排序,从小到大
        g.sort()  # 使小胃口的孩子和小饼干排列在前
        result = 0  # 结果初始为0
        for i in range(len(g)):  # 遍历孩子数组
            for j in range(len(s)):  # 遍历饼干数组
                if g[i] > s[j]:  # 意味着饼干不能满足孩子胃口,直接跳过,寻找下一块饼干
                    continue
                else:
                    s[j] = 0  # 满足条件则将当前饼干置零,防止后续再被使用
                    result += 1
                    break
        return result

优化版本,不需要使用两个for循环,降低时间复杂度:

python 复制代码
class Solution:
    def findContentChildren(self, g: List[int], s: List[int]) -> int:
        s.sort()
        g.sort()
        index = 0  # 用一个index来遍历胃口
        for i in range(len(s)):  # for循环遍历饼干
            if index < len(g) and g[index] <= s[i]:  # 仅当满足条件时,index才会+1
                index += 1
        return index  # 返回index,也就是消耗的饼干数

这里必须外层遍历饼干,内层遍历胃口才可以,因为外层循环的i是固定移动的,内层的index只有在满足条件时才会移动,如果交换顺序就会导致一直在用最小的饼干来对比所有孩子的胃口,从而无法得出结果。

376.摆动序列

题目链接

讲解链接

思路:局部最优------删除单调坡度上的节点(不包括单调坡度两端的节点),那么这个坡度就可以有两个局部峰值整体最优------整个序列有最多的局部峰值,从而达到最长摆动序列

实际上不需要进行删除操作,因为题目要求的是最长摆动子序列的长度,所以只需要统计数组的峰值数量就可以了(相当于是删除单一坡度上的节点,然后统计长度)。如果前一对差值prediff与当前对差值curdiff的乘积小于0,那么就说明当前是一处摆动。代码如下:

python 复制代码
class Solution:
    def wiggleMaxLength(self, nums: List[int]) -> int:
        if len(nums) <= 1:  # 如果数组长度小于等于1,那么则直接返回数组的长度
            return len(nums)
        prediff, curdiff, result = 0, 0, 1  # 初始化前一对差值,当前差值和结果,因为输出的结果是序列的长度,所以结果的初值要设置为1(单纯计算正负差值的对数的结果与序列长度相差1)
        for i in range(1, len(nums)):  # 遍历数组,从1开始
            curdiff = nums[i] - nums[i - 1]  # 计算当前差值
            if curdiff * prediff <= 0 and curdiff != 0:  # 若当前差与前一对差乘起来的结果是负数或0,且当前差值不为0,那么说明出现了摆动
                result += 1  # 结果+1
                prediff = curdiff  # 只有出现摆动时才令前一对差等于当前差
        return result

53.最大子数组和

题目链接

讲解链接

暴力解法,容易想到但会超时。

python 复制代码
class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        result = float('-inf')  # 结果初始为无穷小
        for i in range(len(nums)):  # i对应遍历的起始位置
            sum = 0  # 每次改变起始位置时都将sum置零
            for j in range(i, len(nums)):  # 每次从j从i开始遍历寻找最大值
                sum += nums[j]
                if sum > result:  # 如果sum大于之前的result,就进行赋值
                    result = sum
        return result

贪心思路:

**局部最优------当前"连续和"为负数的时候立刻放弃,从下一个元素重新计算"连续和",因为负数加上下一个元素 "连续和"只会越来越小。**全局最优------选取最大"连续和"

遍历 nums,从头开始用sum累积,如果sum一旦加上numsi变为负数,那么就应该从 numsi+1开始从 0 累积sum了,因为已经变为负数的sum,只会拖累总和。

这相当于是暴力解法中的不断调整最大子序和区间的起始位置

python 复制代码
class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        result = float('-inf')  # result初始为无穷小
        sum = 0  # 连续和初始为0
        for i in range(len(nums)):  # 遍历数组
            sum += nums[i]  # 将第i个元素加到连续和上
            if sum > result:  # 如果当前连续和大于result,则更新result的值
                result = sum
            if sum < 0:  # 如果连续和小于0,则直接舍弃
                sum = 0  # 将连续和置零
                continue  # 从下一个i开始重新计算,类似于暴力法的移动起始位置
        return result
相关推荐
马***4115 小时前
适配成人英语学习痛点,打造落地性强的学习辅助方式
人工智能·学习
小拉达不是臭老鼠8 小时前
Unity学习_ScriptableObject
学习·unity
MartinYeung58 小时前
[论文学习]LLM 与其他 AI 模型的隐私考量:输入与输出隐私框架方法
人工智能·学习
(●—●)橘子……9 小时前
力扣第503场周赛练习理解
python·学习·算法·leetcode·职场和发展·周赛
AOwhisky11 小时前
MySQL 学习笔记(第一期):数据库基础与 MySQL 初探
运维·数据库·笔记·学习·mysql·云计算
try2find12 小时前
Agent学习之补充my_plan_solve_agent
学习
想你依然心痛12 小时前
HarmonyOS 6(API 23)实战:打造“光码智学舱“——AI编程学习新范式
学习·ar·ai编程·harmonyos·智能体
一口吃俩胖子14 小时前
【脉宽调制DCDC功率变换学习笔记023】渐进分析法
笔记·学习
m0_3771081414 小时前
pid学习
学习
爱喝水的鱼丶14 小时前
SAP-ABAP:SAP基础数据校验工具开发系列博客(共5篇)第三篇:SAP接口对接开发:实现数据的实时/批量校验交互
运维·数据库·学习·性能优化·sap·abap·经验交流