【四】【算法分析与设计】贪心算法的初见

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 * 10(4)

  • 0 <= s.length <= 3 * 10(4)

  • 1 <= g[i], s[j] <= 2(31) - 1

 
class Solution {
public:int findContentChildren(vector<int>& children, vector<int>& cookies) {sort(children.begin(), children.end());sort(cookies.begin(), cookies.end());int child = 0, cookie = 0;while (child < children.size() && cookie < cookies.size()) {if (children[child] <= cookies[cookie])++child;++cookie;}return child;}
};

问题的核心是尽可能满足更多孩子的胃口,每个孩子最多能得到一块饼干,每块饼干也只能分给一个孩子,给定一个孩子数组children代表每个孩子的胃口值,一个饼干数组cookies代表每块饼干的大小,求最多有多少孩子能得到饼干满足胃口。

sort(children.begin(), children.end());这行代码将children数组按胃口值从小到大排序。

sort(cookies.begin(), cookies.end());这行代码将cookies数组按饼干大小从小到大排序。

int child = 0, cookie = 0;初始化两个变量childcookie,分别表示当前考虑到的孩子和饼干的索引。

while (child < children.size() && cookie < cookies.size()) {这个循环继续执行直到所有孩子都被考虑过或所有饼干都被尝试分配。

if (children[child] <= cookies[cookie]) ++child;如果当前饼干的大小能满足当前孩子的胃口,那么这个孩子被满足,移动到下一个孩子。

++cookie;无论当前的饼干是否能满足当前的孩子,都将考虑下一块饼干。

时间复杂度和空间复杂度

时间复杂度:O(nlogn)。主要时间开销来自于排序childrencookies数组,假设childrencookies的长度分别为m和n,那么时间复杂度为O(mlogm + nlogn)。遍历数组的过程时间复杂度为O(m+n),所以总体时间复杂度为O(nlogn),这里n是两个数组中较长的那个的长度。

空间复杂度:O(1)。除了输入的数组外,我们只使用了常数空间。

135. 分发糖果

n 个孩子站成一排。给你一个整数数组 ratings 表示每个孩子的评分。

你需要按照以下要求,给这些孩子分发糖果:

  • 每个孩子至少分配到 1 个糖果。

  • 相邻两个孩子评分更高的孩子会获得更多的糖果。

请你给每个孩子分发糖果,计算并返回需要准备的 最少糖果数目

示例 1:

输入:ratings = [1,0,2] 输出:5 解释:你可以分别给第一个、第二个、第三个孩子分发 2、1、2 颗糖果。

示例 2:

输入:ratings = [1,2,2] 输出:4 解释:你可以分别给第一个、第二个、第三个孩子分发 1、2、1 颗糖果。 第三个孩子只得到 1 颗糖果,这满足题面中的两个条件。

提示:

  • n == ratings.length

  • 1 <= n <= 2 * 10(4)

  • 0 <= ratings[i] <= 2 * 10(4)

 
class Solution {
public:int candy(vector<int>& ratings) {int size = ratings.size();if (size < 2) {return size;}vector<int> num(size, 1);for (int i = 1; i < size; ++i) {if (ratings[i] > ratings[i - 1]) {num[i] = num[i - 1] + 1;}}for (int i = size - 1; i > 0; --i) {if (ratings[i] < ratings[i - 1]) {num[i - 1] = max(num[i - 1], num[i] + 1);}}return accumulate(num.begin(), num.end(),0); // std::accumulate 可以很方便地求和}
};

定义变量 size 为评分数组 ratings 的长度。

如果 size 小于 2,直接返回 size。因为如果只有一个孩子,那他就是唯一的获得糖果的人,直接返回1;如果没有孩子,返回0。

初始化一个大小与 ratings 相同,值全为1的数组 num。这一步确保了每个孩子至少得到一颗糖果。

第一次遍历:从左到右遍历 ratings

如果当前孩子(i对应孩子)的评分高于左边的孩子(ratings[i] > ratings[i - 1]),则当前孩子得到的糖果数应该比左边的孩子多一颗(num[i] = num[i - 1] + 1)。

第二次遍历:从右到左遍历 ratings

如果当前孩子(i-1对应孩子)的评分高于右边的孩子(ratings[i] < ratings[i - 1]),则左边的孩子得到的糖果数应该是其原本的数目和右边孩子的糖果数加一中的较大值(num[i - 1] = max(num[i - 1], num[i] + 1))。

最后,使用 accumulate 函数对 num 数组进行求和,得到总共需要的糖果数,并返回这个值。accumulate 函数起始值为0,意味着从0开始累加 num 数组中所有元素的值。

accumulate函数

accumulate 函数是 C++ 标准库中 <numeric> 头文件提供的一个非常实用的数值累加函数。它用于计算一个给定范围内所有元素的累加和,或者在提供了自定义操作时,按照该操作进行累加。accumulate 的基本用法是计算序列的总和,但通过自定义加法操作,它也可以用于更复杂的累加操作,如累乘。

基本用法

基础版本的 accumulate 接受三个参数:序列的开始迭代器、结束迭代器和累加的初始值。如果不指定操作,则默认进行加法操作。下面是一个简单的例子:

 
#include <numeric> // 引入accumulate的头文件
#include <vector>std::vector<int> v = {1, 2, 3, 4, 5};
int sum = std::accumulate(v.begin(), v.end(), 0); // 计算总和

在这个例子中,accumulate0 开始,将 v 中的每个元素相加,计算出总和为 15

使用自定义操作

accumulate 还允许你指定一个自定义的二元操作函数,来代替默认的加法操作。这个二元操作接受两个参数:累加值(到当前为止的结果)和序列中的当前元素。这使得 accumulate 变得非常灵活,可以实现各种复杂的累加逻辑。

例如,使用 accumulate 来计算一个数列的乘积:

 
#include <numeric>
#include <vector>std::vector<int> v = {1, 2, 3, 4, 5};
int product = std::accumulate(v.begin(), v.end(), 1, [](int a, int b) {return a * b;
});

这里,初始值设为 1(乘法的单位元),并通过一个 lambda 表达式指定乘法为累加操作。最终,product 的值为 120,即 1*2*3*4*5 的结果。

注意事项

accumulate 默认使用加法操作时,累加初始值的类型决定了整个操作的类型。例如,如果初始值为整数,那么即使数组是浮点数,累加结果也会被截断为整数。因此,选择合适的初始值类型是非常重要的。

435. 无重叠区间

给定一个区间的集合 intervals ,其中 intervals[i] = [start(i), end(i)] 。返回 需要移除区间的最小数量,使剩余区间互不重叠

示例 1:

输入: intervals = [[1,2],[2,3],[3,4],[1,3]] 输出: 1 解释: 移除 [1,3] 后,剩下的区间没有重叠。

示例 2:

输入: intervals = [ [1,2], [1,2], [1,2] ] 输出: 2 解释: 你需要移除两个 [1,2] 来使剩下的区间没有重叠。

示例 3:

输入: intervals = [ [1,2], [2,3] ] 输出: 0 解释: 你不需要移除任何区间,因为它们已经是无重叠的了。

提示:

  • 1 <= intervals.length <= 10(5)

  • intervals[i].length == 2

  • -5 * 10(4) <= start(i) < end(i) <= 5 * 10(4)

 
int eraseOverlapIntervals(vector<vector<int>>& intervals) {if (intervals.empty()) {return 0;}int n = intervals.size();sort(intervals.begin(), intervals.end(), [](vector<int> a, vector<int> b) {return a[1] < b[1];});int total = 0, prev = intervals[0][1];for (int i = 1; i < n; ++i) {if (intervals[i][0] < prev) {++total;} else {prev = intervals[i][1];}}return total;}

检查区间数组是否为空

if (intervals.empty()) { return 0; }如果区间数组为空,则没有需要移除的区间,直接返回0。

获取区间数组的大小

int n = intervals.size();这里定义了一个变量 n 来存储区间数组的长度。

按区间结束时间排序

sort(intervals.begin(), intervals.end(), [](vector<int> a, vector<int> b) { return a[1] < b[1]; });使用标准库函数 sort,通过自定义的比较函数,将区间按照结束时间升序排序。这样做的目的是尽可能让区间不重叠,因为结束得早的区间留给后面的区间的空间就越多。

初始化计数器和前一个区间的结束右端点

int total = 0, prev = intervals[0][1];初始化需要移除的区间数量 total 为0,并将 prev 设置为第一个区间的结束时间。prev 用于记录当前不重叠区间的最后一个区间的结束时间。

遍历区间数组,确定需要移除的区间数量

for (int i = 1; i < n; ++i) { if (intervals[i][0] < prev) { ++total; } else { prev = intervals[i][1]; } }从第二个区间开始遍历,如果当前区间的开始时间小于前一个区间的结束时间 prev,说明这两个区间重叠,需要移除一个区间,因此 total 自增1。如果不重叠,更新 prev 为当前区间的结束时间,继续向后比较。

标准库函数sort

C++ 标准库中的 sort 函数是一个非常强大且灵活的排序算法,主要用于对数组或容器内的元素进行排序。它位于 <algorithm> 头文件中。sort 函数可以对一个序列进行默认的升序排序,也可以通过自定义比较函数来指定排序规则。

基本用法

默认情况下,sort 对序列进行升序排序。如果你想对一个数组或者 vector 排序,可以这样使用:

 
#include <algorithm> // 引入算法库
#include <vector>std::vector<int> v = {4, 2, 5, 3, 1};
std::sort(v.begin(), v.end());

在上述代码中,v.begin()v.end() 分别是容器 v 的起始迭代器和终止迭代器,sort 函数会将 v 中的元素从小到大排序。

自定义比较函数

sort 函数允许你通过自定义比较函数来指定排序规则,这让你能够实现复杂的排序逻辑,比如降序排序或者根据对象的某个属性排序。

自定义比较函数可以是一个普通函数,也可以是一个lambda表达式。比较函数需要接受两个参数(被比较的元素),并返回一个布尔值,指示第一个参数是否应该位于第二个参数之前。

使用普通函数作为比较函数

 
bool compare(int a, int b) {return a > b; // 降序排序
}std::vector<int> v = {4, 2, 5, 3, 1};
std::sort(v.begin(), v.end(), compare);

使用 Lambda 表达式

Lambda 表达式提供了一种便捷的方式来定义临时的比较函数,这在实现简单的自定义排序规则时非常有用:

 
std::vector<int> v = {4, 2, 5, 3, 1};
std::sort(v.begin(), v.end(), [](int a, int b) {return a > b; // 降序排序
});

对象排序

如果你想根据对象的某个属性排序,可以这样做:

 
struct Person {std::string name;int age;
};bool compareByAge(const Person& a, const Person& b) {return a.age < b.age; // 按年龄升序排序
}std::vector<Person> people = {{"Alice", 30}, {"Bob", 25}, {"Carol", 20}};
std::sort(people.begin(), people.end(), compareByAge);

或者使用 Lambda 表达式:

 
std::sort(people.begin(), people.end(), [](const Person& a, const Person& b) {return a.age < b.age; // 按年龄升序排序
});

结尾

最后,感谢您阅读我的文章,希望这些内容能够对您有所启发和帮助。如果您有任何问题或想要分享您的观点,请随时在评论区留言。

同时,不要忘记订阅我的博客以获取更多有趣的内容。在未来的文章中,我将继续探讨这个话题的不同方面,为您呈现更多深度和见解。

谢谢您的支持,期待与您在下一篇文章中再次相遇!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/275049.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

提高螺栓连接强度——SunTorque智能扭矩系统

螺栓连接是工程中常见的一种连接方式&#xff0c;其强度对于设备的稳定性和安全性具有至关重要的影响。然而&#xff0c;由于各种因素的影响&#xff0c;螺栓连接在使用过程中往往会出现松动、断裂等问题&#xff0c;导致设备故障和安全隐患。因此&#xff0c;提高螺栓连接的强…

Kanebo HITECLOTH 高科技擦镜布介绍

Kanebo HITECLOTH&#xff0c;这款由日本KBSeiren公司制造的高科技擦镜布&#xff0c;以其卓越的清洁能力和超柔软的布质&#xff0c;成为了市场上备受瞩目的产品。 材质与特性 HITECLOTH采用0.1旦尼尔特级高级微纤维制造&#xff0c;质地细致、坚韧、不起颗粒。这种纤维的特…

利用HubSpot出海CRM和人工智能技术提升出海业务的效率和效果

在当今数字化时代&#xff0c;智能化营销已经成为企业获取客户和扩大市场份额的关键策略。特别是对于出海业务而言&#xff0c;利用智能化营销技术来应对不同文化、语言和市场的挑战&#xff0c;已经成为企业竞争的关键优势。今天运营坛将带领大家探讨如何利用HubSpot CRM和人工…

网络流量监控软件AnaTraf:优化性能、排除故障的最佳选择

目录 导言 网络流量监控的重要性 AnaTraf网络万用表的功能与优势 网络故障排除与优化网络性能 结论 导言 在当今数字化时代&#xff0c;计算机网络已经成为企业和组织的核心基础设施。然而&#xff0c;网络流量的管理和监控对于确保网络性能的稳定和优化至关重要。本文将介…

GIS软件应用(二)

任务&#xff1a; 1. 正确划分渔网并裁剪出研究区域 2. 渔网与poi数据正确空间链接并统计网格内类别POI数量 步骤&#xff1a; 将南京市边界进行投影变换&#xff0c;具体看我的这篇文章&#xff1a;GIS软件应用&#xff08;一&#xff09;-CSDN博客 选择ArcToolbox中的 Cr…

java八股文 笔记(持续更新中~)

1 Redis 2Mysql 3JVM 4java基础底层 5 spring 6 微服务 7.......(持续更新) One:Redis篇 1.穿透 2&#xff1a;击穿 3&#xff1a;雪崩 3 33 4:双写一致 5.持久化 2 JVM: 2&#xff1a; 3&#xff1a; 4&#xff1a; 5&#xff1a; 6&#xff1a; 7&#xff…

【Scrapy】京东商品数据可视化

【Scrapy】京东商品数据可视化 文章目录 【Scrapy】京东商品数据可视化  &#x1f449;引言&#x1f48e;一、爬取数据&#xff1a;1.1 scrapy爬虫库简介&#xff1a;1.2 技术实现&#xff1a;1.2.1搭建框架结构1.2.2 分析网页结构 二、数据保存&#xff1a;三、数据读取以及…

企业计算机服务器中了eking勒索病毒怎么办?Eking勒索病毒解密工具流程

网络数据安全问题一直是众多企业关心的主要话题&#xff0c;网络在为企业提供便利的同时&#xff0c;也为企业数据安全带来未知的隐患。近日&#xff0c;云天数据恢复中心接到许多企业求助&#xff0c;企业的计算机服务器遭到了eking勒索病毒攻击导致企业计算机服务器系统瘫痪无…

JMeter使用记录

文章目录 概述从0创建一个测试场景线程组配置元件CSV Data Set ConfigHTTP信息头管理器HTTP Cookie管理器HTTP请求默认值 逻辑控制器简单控制器IF控制器循环控制器while控制器 取样器HTTP取样 前置/后置处理器BeanShell处理器JSR223处理器 监听器查看结果树聚合报告汇总报告 概…

计算机网络:关键性能指标与非性能特征解析

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

力扣每日一题 在受污染的二叉树中查找元素 哈希 DFS 二进制

Problem: 1261. 在受污染的二叉树中查找元素 思路 &#x1f468;‍&#x1f3eb; 灵神题解 &#x1f496; 二进制 时间复杂度&#xff1a;初始化为 O ( 1 ) O(1) O(1)&#xff1b;find 为 O ( m i n ( h , l o g 2 t a r g e t ) O(min(h,log_2target) O(min(h,log2​targ…

PyTorch之完整的神经网络模型训练

简单的示例&#xff1a; 在PyTorch中&#xff0c;可以使用nn.Module类来定义神经网络模型。以下是一个示例的神经网络模型定义的代码&#xff1a; import torch import torch.nn as nnclass MyModel(nn.Module):def __init__(self):super(MyModel, self).__init__()# 定义神经…

云计算OpenStack KVM迁移

动态迁移 static migration 静态迁移 cold migration 冷迁移 offline migration 离线迁移 live migration 动态迁移 hot migration 热迁移 online migration 在线迁移 衡量 整体迁移时间 服务器停机时间 性能影响(迁移后和其它客户机) 特点 负载均衡 解除硬件依赖…

企智汇数字化项目管理平台,助力企业高效项目管理!数字化转型必备!

数字化项目管理平台是一种集成了先进项目信息技术的管理工具&#xff0c;旨在帮助组织更有效地管理项目&#xff0c;实现项目目标的顺利完成。以下是企智汇数字化项目管理平台的一些核心特点和功能&#xff1a; 1. 统一的信息管理&#xff1a;企智汇数字化项目管理平台能够将项…

OpenCASCADE开发指南<四>:OCC 数据类型和句柄

一个软件首先要规定能处理的数据类型&#xff0c; 其次要实现三项最基本的功能——引用管理、内存管理和异常管理。在 OCC 中&#xff0c;这三项功能分别对应基础类中的句柄、内存管理器和异常类。 1 数据类型 在基本概念篇里&#xff0c;已经介绍了 OCC 数据类型的分类&…

网络工程师——2024自学

一、怎样从零开始学习网络工程师 当今社会&#xff0c;人人离不开网络。整个IT互联网行业&#xff0c;最好入门的&#xff0c;网络工程师算是一个了。 什么是网络工程师呢&#xff0c;简单来说&#xff0c;就是互联网从设计、建设到运行和维护&#xff0c;都需要网络工程师来…

工会排队模式:引领创新消费体验的新潮流

在互联网和电子商务的浪潮下&#xff0c;消费者的购物需求与期待正在持续升级。为了迎合这一趋势&#xff0c;工会排队模式应运而生&#xff0c;以其独特的消费体验方式引领市场潮流。 工会排队模式打破了传统电商的桎梏&#xff0c;通过现金返还机制为购物赋予了新的定义。这一…

如何使用 request-promise 在发送请求时使用代理ip?

今天&#xff0c;逛某乎&#xff0c;刷到这个问题&#xff0c;如何在使用 request-promise 时使用代理? 实际不难&#xff0c;我们一起来看看。 如何解决这个问题&#xff0c;我们要知道request-promise 是一个基于Promise的HTTP请求库&#xff0c;可以简化Node.js中发送HTTP…

vue中如何查看组件有哪些函数与变量

在开发的过程中&#xff0c;经常用到他人的框架&#xff0c;特别是开源框架比如element,uniapp等。其中就涉及到框架里对应的组件。而组件里又有哪些内置的函数&#xff0c;我们通常是去查官方文档。然后很多的时候需求的多样性&#xff0c;要改的地方也是不一样的&#xff0c;…

二、vue-cli项目搭建

系列文章&#xff1a; vue实战&#xff08;商城后台管理系统&#xff09;&#xff1a;http://t.csdnimg.cn/f6Fqa vue.js :http://t.csdnimg.cn/mljxv 目录 系列文章&#xff1a; vue实战&#xff08;商城后台管理系统&#xff09;&#xff1a;http://t.csdnimg.cn/f6Fqa vue…