首页 > 编程语言 >代码随想录算法训练营第二十七天|455分发饼干、376摆动序列、53最大子序和

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

时间:2024-12-19 23:26:40浏览次数:6  
标签:currentSum max 随想录 455 53 up down 序列 maxSum

day27 贪心算法 part01

贪心算法没有什么规律可言, 没有思路就立刻看题解

1. 455分发饼干

为了满足更多的小孩,就不要造成饼干尺寸的浪费。

大尺寸的饼干既可以满足胃口大的孩子也可以满足胃口小的孩子,那么就应该优先满足胃口大的。

先将饼干数组和小孩数组排序,然后从后向前遍历小孩数组,用大饼干优先满足胃口大的,并统计满足小孩数量。

class Solution {
public:
    int findContentChildren(vector<int>& g, vector<int>& s) {
        sort(g.begin(), g.end());
        sort(s.begin(), s.end());
        int index = s.size() - 1; // 饼干数组的下标
        int sum = 0;
        for (int i = g.size() - 1; i >= 0; i--) { // 遍历胃口
            if (index >= 0 && s[index] >= g[i]) { // 遍历饼干
                sum++;
                index--;
            }
        }
        return sum;
    }
};

2. 376摆动序列

  • 摆动序列的定义
    1. 什么是摆动序列?
      • 一组数字的差值必须严格交替正负。例如,差值是正数、负数、正数……或者是负数、正数、负数……
      • 如果差值重复(比如连续两个正数或负数差值)或为零,就不再是摆动序列。
    2. 子序列的定义
      • 子序列是通过从原始序列中删除一些元素(可以删除,也可以不删除)获得,且剩下的元素顺序不变。
    3. 目标
      • 给定一个整数数组 nums,找到其中最长的摆动子序列的长度。

    解题思路
    1. 我们不需要真的去构造摆动子序列,而是记录摆动序列的长度即可。
    2. 核心逻辑:
      • 用两个变量:
        • up:记录以正差(上升趋势)结束的最长摆动序列长度。
        • down:记录以负差(下降趋势)结束的最长摆动序列长度。
      • 遍历数组时,比较当前元素和前一个元素:
        • 如果当前差值是正的,由于需要是摆动序列,所有是在以负差(下降趋势)结束的最长摆动序列长度上+1,即更新 up = down + 1
        • 如果当前差值是负的,由于需要是摆动序列,所有是在以正差(上升趋势)结束的最长摆动序列长度上+1,即更新 down = up + 1
      • 每次更新后,updown 记录的就是以正差或负差结尾的摆动序列的长度。
    3. 总结规律
      • 正差(上升)时up 的长度依赖于上一次的 down 长度,因为正差必须接在负差后。
      • 负差(下降)时down 的长度依赖于上一次的 up 长度,因为负差必须接在正差后。
    4. 最终答案就是 max(up, down)
class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        int n = nums.size();
        if (n < 2) return n;

        // `up` 表示以正差结尾的最长摆动序列长度
        // `down` 表示以负差结尾的最长摆动序列长度
        // up = 1,down = 1(序列最少有一个元素,长度初始为 1)。for循环从第二个元素开始(即i=1开始)
        int up = 1, down = 1;

        for (int i = 1; i < n; ++i) {
            if (nums[i] > nums[i - 1]) {
                // 当前差值为正,则以正差结尾的序列长度增加
                up = down + 1;
            } else if (nums[i] < nums[i - 1]) {
                // 当前差值为负,则以负差结尾的序列长度增加
                down = up + 1;
            }
        }

        // 结果为两种最长摆动序列中的最大值
        return max(up, down);
    }
};

3. 53最大子序和

贪心法解题思路
  1. 局部最优:
    对于当前遍历到的元素,有两种选择:
    • 要么将当前元素加入之前的子数组中(累加当前元素)。
    • 要么舍弃之前的子数组,重新从当前元素开始。
      局部最优策略就是取两者的较大值。
  2. 全局最优:
    在每一步的局部最优中,不断更新一个记录全局最大值的变量。
  3. 具体步骤:
    • 初始化 currentSum 为 0,表示当前子数组的和。
    • 初始化 maxSumnums[0],因为至少有一个元素,最大子数组和不能小于数组中的某个元素。
    • 遍历数组中的每个元素:
      • 如果当前子数组和加上当前元素的值小于当前元素的值,那么直接从当前元素重新开始。
      • 更新全局最大值。
示例

输入数组:[-2, 1, -3, 4, -1, 2, 1, -5, 4]

执行过程:

  • 初始值:maxSum = -2, currentSum = 0
  • 遍历:
    • num = -2currentSum = max(-2, 0 + (-2)) = -2maxSum = max(-2, -2) = -2
    • num = 1currentSum = max(1, -2 + 1) = 1maxSum = max(-2, 1) = 1
    • num = -3currentSum = max(-3, 1 + (-3)) = -2maxSum = max(1, -2) = 1
    • num = 4currentSum = max(4, -2 + 4) = 4maxSum = max(1, 4) = 4
    • num = -1currentSum = max(-1, 4 + (-1)) = 3maxSum = max(4, 3) = 4
    • num = 2currentSum = max(2, 3 + 2) = 5maxSum = max(4, 5) = 5
    • num = 1currentSum = max(1, 5 + 1) = 6maxSum = max(5, 6) = 6
    • num = -5currentSum = max(-5, 6 + (-5)) = 1maxSum = max(6, 1) = 6
    • num = 4currentSum = max(4, 1 + 4) = 5maxSum = max(6, 5) = 6

最终返回:maxSum = 6

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int maxSum = nums[0]; // 全局最大和
        int currentSum = 0;   // 当前子数组和
        for (int num : nums) {
            // 更新当前子数组和:要么从当前元素重新开始,要么继续累加
            currentSum = max(num, currentSum + num);
            // 更新全局最大子数组和
            maxSum = max(maxSum, currentSum);
        }
        return maxSum;
    }
};

标签:currentSum,max,随想录,455,53,up,down,序列,maxSum
From: https://blog.csdn.net/qq_43405634/article/details/144593683

相关文章

  • P4556 [Vani有约会] 雨天的尾巴 /【模板】线段树合并
    [Vani有约会]雨天的尾巴/【模板】线段树合并题目背景深绘里一直很讨厌雨天。灼热的天气穿透了前半个夏天,后来一场大雨和随之而来的洪水,浇灭了一切。虽然深绘里家乡的小村落对洪水有着顽固的抵抗力,但也倒了几座老房子,几棵老树被连根拔起,以及田地里的粮食被弄得一片狼藉。无......
  • 534. 游戏玩法分析 III - 力扣(LeetCode)
    534.游戏玩法分析III-力扣(LeetCode)目标输入输入:Activitytable:player_iddevice_idevent_dategames_played122016/3/15122016/5/26132017/6/251312016/3/20342018/7/35输出输出:player_idevent_dategames_played_so_far12016/3/1512016/5/21112017/6/251232016/3/......
  • P7531 [USACO21OPEN] Routing Schemes P 题解
    best定理居然还有运用范围。思路考虑如何来判断是否有解。由于每一条边都需要用到。但是它是使用很多条路径进行覆盖。我们考虑一个很巧妙的转化。建立一个超级源点,源点向每一条路径的开头连一条边。每一条路径的结尾向源点连一条边,这样一条路径就变成了一个回路。把所有......
  • 【代码随想录】刷题记录(76)-子集
    题目描述:给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例1:输入:nums=[1,2,3]输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,3]]示例2:输入:nums=[0]输出:[[......
  • 「Mac玩转仓颉内测版53」基础篇15 - 函数组合与链式调用
    本篇将介绍函数组合(FunctionComposition)与链式调用(Chaining)。通过组合多个小函数或方法,可以有效提升代码的可读性与复用性,避免重复逻辑。链式调用则进一步简化了代码结构,使逻辑表达更加流畅。关键词函数组合链式调用代码复用简化逻辑一、函数组合的概念函数组合指将......
  • 睡岗和玩手机数据集,4653张原始图,支持YOLO,VOC XML,COCO JSON格式的标注
    睡岗和玩手机数据集,4653张原始图,支持YOLO,VOCXML,COCOJSON格式的标注数据集分割训练组70%        3257图片有效集20%        931图片测试集10%        465图片预处理没有采用任何预处理步骤。增强未应用任何增......
  • imx6ull RTC-S35390A时钟 LINUX增加驱动
    CPU平台:imx6ull软件平台:qt+linux4.1.15驱动部分:在驱动编写中,对S35390A的地址填写为0x30+指令,实际只需要用到0x30、0x31、0x32。(i2c-imx.c中发送和接收时,设备地址,有一个左移一位)1.i2c设备树中增加:rtc:rtc-s35390a@60{ compatible="s35390a"; reg=<0x30>;};compa......
  • MBI5353Q聚积车规级48通道点阵屏/RGB/直显屏AEC-Q100
    MBI5353Q是一款专为车规级动态LED图形应用设计的48通道PWM恒流LED驱动芯片,支持高达1:32的时间复用扫描应用,内置48K位SRAM,可通过片上PWM控制实现多种灰度深度选择(16/15/14/13位)。此产品旨在提升LED显示屏的刷新率和图像质量,特别适合车用动态显示、广告屏及工业控制应用。技术参......
  • 代码随想录算法训练营第三十二天|动态规划理论基础|LC509.肥波那些数|LC70.爬楼梯|LC7
    动态规划理论基础    解释:动态规划,英文:DynamicProgramming,简称DP;如果某一问题有很多重叠子问题,使用动态规划是最有效的。动态规划五部曲:    1、确定dp数组(dptable)以及下标的含义;    2、确定递推公式;    3、dp数组如何初始化;   ......
  • 代码随想录算法训练营第三十四天|LC62.不同路径|LC63.不同路径Ⅱ
    62.不同路径-力扣(LeetCode)①确定dp数组以及下标的含义:     dp[i][j]:表示从(0,0)出发,到(i,j)有dp[i][j]条不同的路径。②确定递推公式:    像要求dp[i][j],只能有两个方向来推导出来,即dp[i-1][j]和dp[i][j-1];此时在回顾一下dp[i-1][j]表示啥,是......