【2251. 花期内花的数目】

来源:力扣(LeetCode)

描述:

给你一个下标从 0 开始的二维整数数组 flowers ,其中 flowers[i] = [starti, endi] 表示第 i 朵花的 花期startiendi (都 包含)。同时给你一个下标从 0 开始大小为 n 的整数数组 peoplepeople[i] 是第 i 个人来看花的时间。

请你返回一个大小为 n 的整数数组 answer ,其中 answer[i] 是第 i 个人到达时在花期内花的 数目

示例 1:

1

输入:flowers = [[1,6],[3,7],[9,12],[4,13]], people = [2,3,7,11]
输出:[1,2,2,2]
解释:上图展示了每朵花的花期时间,和每个人的到达时间。
对每个人,我们返回他们到达时在花期内花的数目。

示例 2:

2

输入:flowers = [[1,10],[3,3]], people = [3,3,2]
输出:[2,2,1]
解释:上图展示了每朵花的花期时间,和每个人的到达时间。
对每个人,我们返回他们到达时在花期内花的数目。

提示:

  • 1 <= flowers.length <= 5 * 104
  • flowers[i].length == 2
  • 1 <= starti <= endi <= 109
  • 1 <= people.length <= 5 * 104
  • 1 <= people[i] <= 109

方法一:差分数组 + 离线查询

思路与算法

本题可以转换为经典的「差分」思想,由于每朵花开的周期是固定的,第 iii 朵花开的周期为 [starti, endi],即区间 [starti, endi] 内每个时间点都有一朵花正处于开放状态,此时假设第 j 个人到达的时间点为 people[j],则此时我们只需要求出 people[j] 时正处于开花状态的花朵数目即可。根据差分的性质,对差分数组求前缀和即可得到当前元素的值,此时我们只需要对区间 [0,people[j]] 之间求前缀和,即可得到时间点为 people[j] 开花的数目。

具体地,由于本题中花开时间的取值范围为 0 ≤ starti ≤ endi ≤ 1090 ,这就决定了我们无法直接使用数组来计算前缀和,但可以将时间点进行离散化,利用有序集合来记录端点的变化量即可,在时间点 starti 上开花的数量增加了 1,在时间点 endi + 1 开花的数量减少了 1。遍历整个 flowers 数组,利用有序集合 cnt 统计每次花开放区间端点的变化量。此时根据差分的性质,只需对所有小于等于 people[j] 的端点变化量求和即可计算出 people[j] 时间点处于开花状态的花朵数目。由于 cnt 本身为有序集合,对其直接遍历即为有序,从小到大累加所有的变化量即可依次得到从早到晚开花的数目。 为了避免每次重复计算,可将 people 从小到大排序,这样可在遍历 people 的同时遍历 cnt。此时可以利用双指针,一个指向数组 people,另一个指针指向有序集合 cnt 即可。

代码:

class Solution {
public:vector<int> fullBloomFlowers(vector<vector<int>>& flowers, vector<int>& persons) {map<int, int> cnt;for (auto &flower : flowers) {cnt[flower[0]]++;cnt[flower[1] + 1]--;}int m = persons.size();vector<int> ves(m);iota(ves.begin(), ves.end(), 0);sort(ves.begin(), ves.end(), [&](int a, int b) {return persons[a] < persons[b];});vector<int> ans(m);int curr = 0;auto it = cnt.begin();for (int x : ves) {while (it != cnt.end() && it->first <= persons[x]) {curr += it->second;it++;}ans[x] = curr;}return ans;}
};

时间 264ms 击败 73.61%使用 C++ 的用户
内存 82.95MB 击败 45.84%使用 C++ 的用户
复杂度分析

  • 时间复杂度:O(nlogn+mlogm),其中 n 表示数组 flowers 的长度,m 表示数组 people 的长度。由于 cnt 为有序集合,因此每次插入的时间为 O(logn),一共需要插入 n 个元素,因此构建有序集合的时间为 O(nlog⁡n),people 排序花费的时间为 O(mlogm),因此总的时间为 O(nlogn+mlogm)。
  • 空间复杂度: O(n+m),其中 n 表示数组 flowers 的长度,m 表示数组 people 的长度。存储 n 个元素的有序集合需要使用的空间为 O(n),由于本题目使用了离线查询,即需要保存 people 的原始索引,使用的空间为 O(m),因此总的空间为 O(n+m)。

方法二:二分查找

思路与算法

第 i 到达的时间为 people[i],假设在 people[i] 时间点之前花开的数目为 x,在 people[i] 时间之前花谢的数目为 y,则在 people[i] 时间点还处于开花状态的数目等于 x − y。我们只需要找到 start ≤ people[i] 的花朵数目,减去 end < people[i] 的花朵数目即为 people[i] 时间点可以看到花开的数目。 根据以上分析,我们可以单独统计起始时间 start 与结束 end,利用二分查找即可快速查找结果。

  • 首先需要将所有的起始时间start、结束时间 end 按照从早到晚进行排序;
  • 设第 i 个人到达的时间 people[i],利用二分查找找到 starti ≤ people[i] 的花朵数目为 x,利用二分查找找到 endi < people[i] 的花朵数目为 y,则第 i 个人可以看到的花朵数目为 x − y;
  • 依次遍历并统计每个人的查询结果即可;

代码:

class Solution {
public:vector<int> fullBloomFlowers(vector<vector<int>> &flowers, vector<int> &persons) {int n = flowers.size();vector<int> starts(n), ends(n);for (int i = 0; i < n; ++i) {starts[i] = flowers[i][0];ends[i] = flowers[i][1];}sort(starts.begin(), starts.end());sort(ends.begin(), ends.end());int m = persons.size();vector<int> ans(m);for (int i = 0; i < m; ++i) {int x = upper_bound(starts.begin(), starts.end(), persons[i]) - starts.begin();int y = lower_bound(ends.begin(), ends.end(), persons[i]) - ends.begin();ans[i] = x - y;}return ans;}
};

时间 248ms 击败 87.50%使用 C++ 的用户
内存 75.33MB 击败 77.08%使用 C++ 的用户
复杂度分析

  • 时间复杂度: O((n+m)×log⁡n)O((n + m) ,其中 n 表示数组 flowers 的长度,m 表示数组 people 的长度。对 start, end 进行排序需要的时间为 O(nlogn),对每个到达的人进行二分查找时需要的时间为 O(logn),一共需要查询 m 次,查询时花费时间为 mlog⁡n,总的时间复杂度为 (n+m) × log⁡n(n + m)。
  • 空间复杂度: O(n),其中 n 表示数组 flowers 的长度。需要单独保存每朵花开的时间点 start 与结束的时间点 end,需要的空间为 O(n),排序需要的空间为 O(logn),总的空间复杂度为 O(n+log⁡n) = O(n)。
    author:力扣官方题解

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构和算法(8):搜索树(二叉搜索树和AVL树)

查找 所谓的查找或搜索&#xff0c;指从一组数据对象中找出符合特定条件者&#xff0c;这是构建算法的一种基本而重要的操作。其中的数据对象&#xff0c;统一地表示和实现为 词条&#xff08;entry&#xff09; 的形式&#xff1b;不同词条之间&#xff0c;依照各自的 关键码…

Caddy Web服务器深度解析与对比:Caddy vs. Nginx vs. Apache

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

canvas手写签名组件

效果图&#x1f447; 代码不多直接粘在这里 <template><div class"border"><canvasref"canvas"width"800"height"500"class"border-success"tabindex"0"mousedown"onMouseDown"/>&…

二叉树题目:二叉树剪枝

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;二叉树剪枝 出处&#xff1a;814. 二叉树剪枝 难度 4 级 题目描述 要求 给定二叉树的根结点 root \texttt{root} root&#xff0c;返回移除了所有…

如何用思维导图做学习计划?

在我们不断追求个人和职业发展的过程中&#xff0c;学习计划起着至关重要的作用。然而&#xff0c;很多人在制定学习计划时常常感到困惑&#xff0c;不知道如何才能制定一份周全且可行的计划。本文将介绍一种结构化思维的方法&#xff0c;以帮助你制定一份高效的学习计划。 首先…

113. 路径总和ii

力扣题目链接(opens new window) 给定一个二叉树和一个目标和&#xff0c;找到所有从根节点到叶子节点路径总和等于给定目标和的路径。 说明: 叶子节点是指没有子节点的节点。 示例: 给定如下二叉树&#xff0c;以及目标和 sum 22&#xff0c; 在路径总和题目的基础上&…

如何使用Etherscan Remix插件验证智能合约

在Moonbeam上验证合约的方式有很多&#xff0c;使用Etherscan Remix插件是最快、最简单的方式。 此示例中&#xff0c;我们展示如何在Remix上激活Etherscan插件并验证简单的增量智能合约。开始之前&#xff0c;请准备以下内容&#xff1a; MetaMask钱包 存有DEV的账户 将验证…

Linux 线程同步(重要) 互斥量

/*三个窗口卖一百张票 */#include<stdio.h> #include<unistd.h> #include<pthread.h> #include<string.h> int tickets 0; void * sellticket(void * arg) {//卖票usleep(7000);while(tickets < 100) {printf("%ld 正在卖第 %d 张票\n",…

34.CSS魔线图标的悬停效果

效果 源码 index.html <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Icon Fill Hover Effects</title> <link rel="stylesheet" h…

基于AIOps实现智慧园区极简IT运维

随着物联网、云平台、大数据、人工智能等技术的发展&#xff0c;并逐步投入到智慧园区的建设&#xff0c;传统园区数字化转型加快。园区的形式包括产业园区、教育园区、制造业园区、科研园区、社区等等&#xff0c;园区形态不断演进和发展&#xff0c;园区网承载的对象和业务也…

通过http发送post请求的三种Content-Type分析

通过okhttp向服务端发起post网络请求&#xff0c;可以通过Content-Type设置发送请求数据的格式。 常用到的三种&#xff1a; 1&#xff09;application/x-www-form-urlencoded; charsetutf-8 2&#xff09;application/json; charsetutf-8 3&#xff09;multipart/form-dat…

go语言unsafe.Pointer与uintptr

以下内容来源go语言圣经 1、unsafe.Pointer&#xff0c;相当于c语言中的void *类型的指针&#xff0c;如果需要运算需要转成uintptr类型的指针 2. uintptr uintptr是一个无符号的整型&#xff0c;它可以保存一个指针地址。 它可以进行指针运算。 uintptr无法持有对象, GC不把…

麒麟信安组织开展国产操作系统技术赋能专题培训

近日&#xff0c;为学习国产操作系统基本概念、使用与运维知识&#xff0c;应对用户单位内部信息系统国产化需求&#xff0c;来自国营洛阳丹城无线电厂的运维工程师们走进麒麟信安&#xff0c;进行了为期一周的操作系统课程学习。 针对客户此次培训需求&#xff0c;结合学员实…

基于php的物流信息公共平台设计与实现

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。今天给大家介绍一篇基于php的物流信息公共平…

JAVA中使用CompletableFuture进行异步编程

JAVA中使用CompletableFuture进行异步编程 1、什么是CompletableFuture CompletableFuture 是 JDK8 提供的 Future 增强类&#xff0c;CompletableFuture 异步任务执行线程池&#xff0c;默认是把异步任 务都放在 ForkJoinPool 中执行。 在这种方式中&#xff0c;主线程不会…

nginx 多层代理 + k8s ingress 后端服务获取客户真实ip 配置

1.nginx http 七层代理 修改命令空间&#xff1a; namespace: nginx-ingress : configmap&#xff1a;nginx-configuration kubectl get cm nginx-configuration -n ingress-nginx -o yaml添加如上配置 compute-full-forwarded-for: “true” forwarded-for-header: X-Forwa…

MySQL学习笔记19

MySQL日志文件&#xff1a;MySQL中我们需要了解哪些日志&#xff1f; 常见日志文件&#xff1a; 我们需要掌握错误日志、二进制日志、中继日志、慢查询日志。 错误日志&#xff1a; 作用&#xff1a;存放数据库的启动、停止和运行时的错误信息。 场景&#xff1a;用于数据库的…

MySQL高级语句(第一部分)

MySQL高级语句(第一部分)一、MySQL进阶查询1、select ----显示表格中一个或数个字段的所有数据记录2、distinct ----不显示重复的数据记录3、where ----有条件查询4、and or ----且 或5、in ----显示已知的值的数据记录6、between ----显示两个值范围内的数据记录7、通配符8、l…

#硬件电路设计VL817-Q7(B0)芯片拓展USB3.0一转四调试心得

供电电路 基于XL4005的电源供电电路 SS34肖特基二极管 ZMM5V1稳压二极管 SMAJ15A TVS &#xff08;注意这个封装搞错5V会短接&#xff09; Vout0.8*[1(R2R3)/R1] D14 SR05静电防护器件 一路稳压两路TVS 共模电感 &#xff1a; 型号&#xff1a; SDCW2012-2-900TF 品牌&#…

OpenAI ChatGPT API 文档之 Embedding

译者注&#xff1a; Embedding 直接翻译为嵌入似乎不太恰当&#xff0c;于是问了一下 ChatGPT&#xff0c;它的回复如下&#xff1a; 在自然语言处理和机器学习领域&#xff0c;"embeddings" 是指将单词、短语或文本转换成连续向量空间的过程。这个向量空间通常被称…