455.分发饼干 ,376. 摆动序列 , 53. 最大子序和

简介: **简介:**本文介绍了三道经典的算法题及其解法,涵盖贪心算法、动态规划等重要思想。第一题“分发饼干”通过贪心策略,将大尺寸饼干优先分配给胃口大的孩子,实现满足最多孩子的目标。第二题“摆动序列”利用差值变化判断峰值,统计最长摆动子序列长度,需处理平坡与边界情况。第三题“最大子数组和”采用动态规划思想,在局部最优中寻找全局最大连续子数组和。三道题目均附有详细解析与C++代码实现,帮助理解算法核心逻辑与实现细节。

 题目:455. 分发饼干

假设你是一位很棒的家长,想要给你的孩子们一些小饼干。但是,每个孩子最多只能给一块饼干。

对每个孩子 i,都有一个胃口值 g[i],这是能让孩子们满足胃口的饼干的最小尺寸;并且每块饼干 j,都有一个尺寸 s[j] 。如果 s[j] >= g[i],我们可以将这个饼干 j 分配给孩子 i ,这个孩子会得到满足。你的目标是尽可能满足越多数量的孩子,并输出这个最大数值。

示例 1:

输入: g = [1,2,3], s = [1,1]

输出: 1

解释:  

你有三个孩子和两块小饼干,3个孩子的胃口值分别是:1,2,3。

虽然你有两块小饼干,由于他们的尺寸都是1,你只能让胃口值是1的孩子满足。

所以你应该输出1。

示例 2:

输入: g = [1,2], s = [1,2,3]

输出: 2

解释:  

你有两个孩子和三块小饼干,2个孩子的胃口值分别是1,2。

你拥有的饼干数量和尺寸都足以让所有孩子满足。

所以你应该输出2.

提示:

1 <= g.length <= 3 * 104

0 <= s.length <= 3 * 104

1 <= g[i], s[j] <= 231 - 1

思考历程与知识点:  

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

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

这里的局部最优就是大饼干喂给胃口大的,充分利用饼干尺寸喂饱一个,全局最优就是喂饱尽可能多的小孩。

可以尝试使用贪心策略,先将饼干数组和小孩数组排序。

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

题解:

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 result = 0;
        for (int i = g.size() - 1; i >= 0; i--) { // 遍历胃口
            if (index >= 0 && s[index] >= g[i]) { // 遍历饼干
                result++;
                index--;
            }
        }
        return result;
    }
};

 题目:376. 摆动序列

如果连续数字之间的差严格地在正数和负数之间交替,则数字序列称为 摆动序列 。第一个差(如果存在的话)可能是正数或负数。仅有一个元素或者含两个不等元素的序列也视作摆动序列。

例如, [1, 7, 4, 9, 2, 5] 是一个 摆动序列 ,因为差值 (6, -3, 5, -7, 3) 是正负交替出现的。

相反,[1, 4, 7, 2, 5] 和 [1, 7, 4, 5, 5] 不是摆动序列,第一个序列是因为它的前两个差值都是正数,第二个序列是因为它的最后一个差值为零。

子序列 可以通过从原始序列中删除一些(也可以不删除)元素来获得,剩下的元素保持其原始顺序。

给你一个整数数组 nums ,返回 nums 中作为 摆动序列 的 最长子序列的长度 。

示例 1:

输入:nums = [1,7,4,9,2,5]

输出:6

解释:整个序列均为摆动序列,各元素之间的差值为 (6, -3, 5, -7, 3) 。

示例 2:

输入:nums = [1,17,5,10,13,15,10,5,16,8]

输出:7

解释:这个序列包含几个长度为 7 摆动序列。

其中一个是 [1, 17, 10, 13, 10, 16, 8] ,各元素之间的差值为 (16, -7, 3, -3, 6, -8) 。

示例 3:

输入:nums = [1,2,3,4,5,6,7,8,9]

输出:2

提示:

1 <= nums.length <= 1000

0 <= nums[i] <= 1000

思考历程与知识点:  

让峰值尽可能的保持峰值,然后删除单一坡度上的节点

在计算是否有峰值的时候,大家知道遍历的下标 i ,计算 prediff(nums[i] - nums[i-1]) 和 curdiff(nums[i+1] - nums[i]),如果prediff < 0 && curdiff > 0 或者 prediff > 0 && curdiff < 0 此时就有波动就需要统计。

这是我们思考本题的一个大题思路,但本题要考虑三种情况:

情况一:上下坡中有平坡

情况二:数组首尾两端

情况三:单调坡中有平坡

题解:

class Solution {
public:
    int wiggleMaxLength(vector<int>& nums) {
        if (nums.size() <= 1) return nums.size();
        int curDiff = 0; // 当前一对差值
        int preDiff = 0; // 前一对差值
        int result = 1;  // 记录峰值个数,序列默认序列最右边有一个峰值
        for (int i = 0; i < nums.size() - 1; i++) {
            curDiff = nums[i + 1] - nums[i];
            // 出现峰值
            if ((preDiff <= 0 && curDiff > 0) || (preDiff >= 0 && curDiff < 0)) {
                result++;
                preDiff = curDiff; // 注意这里,只在摆动变化的时候更新prediff
            }
        }
        return result;
    }
};

 题目:53. 最大子数组和

给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

子数组 是数组中的一个连续部分。

示例 1:

输入:nums = [-2,1,-3,4,-1,2,1,-5,4]

输出:6

解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。

示例 2:

输入:nums = [1]

输出:1

示例 3:

输入:nums = [5,4,-1,7,8]

输出:23

提示:

1 <= nums.length <= 105

-104 <= nums[i] <= 104

思考历程与知识点:  

局部最优的情况下,并记录最大的“连续和”,可以推出全局最优。

从代码角度上来讲:遍历 nums,从头开始用 count 累积,如果 count 一旦加上 nums[i]变为负数,那么就应该从 nums[i+1]开始从 0 累积 count 了,因为已经变为负数的 count,只会拖累总和。

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

那有同学问了,区间终止位置不用调整么? 如何才能得到最大“连续和”呢?

区间的终止位置,其实就是如果 count 取到最大值了,及时记录下来了。

题解:

class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int result = INT32_MIN;
        int count = 0;
        for (int i = 0; i < nums.size(); i++) {
            count += nums[i];
            if (count > result) { // 取区间累计的最大值(相当于不断确定最大子序终止位置)
                result = count;
            }
            if (count <= 0) count = 0; // 相当于重置最大子序起始位置,因为遇到负数一定是拉低总和
        }
        return result;
    }
};


                     

相关文章
|
5月前
|
存储 机器学习/深度学习 缓存
软考软件评测师——计算机组成与体系结构(分级存储架构)
本内容全面解析了计算机存储系统的四大核心领域:虚拟存储技术、局部性原理、分级存储体系架构及存储器类型。虚拟存储通过软硬件协同扩展内存,支持动态加载与地址转换;局部性原理揭示程序运行特性,指导缓存设计优化;分级存储架构从寄存器到外存逐级扩展,平衡速度、容量与成本;存储器类型按寻址和访问方式分类,并介绍新型存储技术。最后探讨了存储系统未来优化趋势,如异构集成、智能预取和近存储计算等,为突破性能瓶颈提供了新方向。
|
监控 安全 Unix
UNIX域套接字(Unix Domain Socket)在安全性和隐私性
UNIX域套接字(Unix Domain Socket)在安全性和隐私性
597 2
|
机器学习/深度学习 算法
【机器学习】正则化 Regularization 过拟合欠拟合
【1月更文挑战第27天】【机器学习】正则化 Regularization 过拟合欠拟合
|
5月前
|
算法
104.二叉树的最大深度 , 111.二叉树的最小深度,222.完全二叉树的节点个数
本内容主要讲解了三道与二叉树相关的算法题及其解法,包括“二叉树的最大深度”、“二叉树的最小深度”和“完全二叉树的节点个数”。通过递归方法(前序或后序遍历)实现求解。 - **最大深度**:利用后序遍历计算根节点到最远叶子节点的路径长度。 - **最小深度**:同样采用后序遍历,但需特别处理单子树为空的情况,确保找到从根到最近叶子节点的路径。 - **完全二叉树节点数**:基于递归后序遍历统计左右子树节点数量并累加。 代码示例清晰展示了递归逻辑,帮助理解二叉树深度与高度的概念及其实现方式。
669. 修剪二叉搜索树 ,108.将有序数组转换为二叉搜索树 , 538.把二叉搜索树转换为累加树
1. **修剪二叉搜索树(669号题)**:通过递归方法,移除值不在指定范围 `[low, high]` 内的节点,同时保持树中剩余节点的相对结构不变。核心思想是根据当前节点值与边界的关系决定保留左子树还是右子树。 2. **将有序数组转换为二叉搜索树(108号题)**:将一个升序排列的数组转化为一棵高度平衡的二叉搜索树。采用分治法,选取数组中间元素作为根节点,递归构建左右子树。即使数组长度为偶数,选择任一中间值均可满足条件。 3. **把二叉搜索树转换为累加树(538号题)**:通过修改二叉搜索树中每个节点的值,使其等于原树中所有大于或等于该节点值的和。
|
5月前
|
算法
459.重复的子字符串,28. 实现 strStr(),剑指Offer 05.替换空格
本内容涵盖三个字符串处理问题的解决方案,包括算法思路与代码实现。 **一、重复的子字符串(459题)**:通过构造新字符串并查找原字符串是否存在其中,巧妙判断是否由重复子串组成,时间复杂度低。 **二、找出字符串中第一个匹配项的下标(28题)**:运用KMP算法构建前缀表优化匹配过程,减少不必要的回溯操作,提高效率。 **三、替换空格(剑指Offer 05题)**:采用双指针法从后向前替换,避免频繁移动元素,空间复杂度更优。以上方法均针对字符串操作的经典问题,展示了高效算法设计的精髓。
|
5月前
|
算法
513.找树左下角的值,112. 路径总和 113.路径总和ii, 106.从中序与后序遍历序列构造二叉树 105.从前序与中序遍历序列构
本内容涵盖了三道与二叉树相关的算法题及其解决方案。第一题“找树左下角的值”通过深度优先搜索(DFS)找到二叉树最底层最左边的节点值。第二题“路径总和”判断是否存在从根到叶子节点的路径,其节点值之和等于目标值。第三题“从中序与后序遍历序列构造二叉树”利用中序和后序遍历结果还原二叉树结构。每个题解均采用递归方法实现,逻辑清晰且高效,适用于处理大规模数据的二叉树问题。
|
5月前
|
算法 测试技术 索引
122.买卖股票的最佳时机II ,55. 跳跃游戏 ,45.跳跃游戏II
**简介:** 本文介绍了三道经典算法题的解法,涵盖贪心算法的核心思想与应用。 1. **买卖股票的最佳时机 II**:通过收集每天的正利润实现最大收益,局部最优推导全局最优。 2. **跳跃游戏**:利用贪心算法扩展覆盖范围,判断是否能到达终点。 3. **跳跃游戏 II**:基于最大覆盖范围计算最小跳跃次数,平衡当前步与下一步的覆盖距离。 三道题目均采用贪心策略,通过优化局部选择实现整体最优解,代码简洁高效,时间复杂度低,适合解决类似问题。
|
11月前
|
数据挖掘 数据安全/隐私保护
抖音运营:解锁流量增长密码
在短视频盛行的时代,抖音成为流量蓝海,众多创作者和品牌竞相涌入。要在激烈竞争中脱颖而出,除了创作优质内容和巧妙运营外,数据分析至关重要。精准定位目标受众,挖掘创意与热门趋势,优化视频制作、剪辑节奏及发布时间,积极互动并分析关键数据指标(如播放量、点赞数、完播率等),不断优化运营策略,才能实现流量快速增长和账号的长期发展。
1179 11
|
安全 Shell 网络安全
设置 码云 SSH 推送和拉取代码
设置 码云 SSH 推送和拉取代码
495 0