每日一题——寻找右区间(排序 + 二分查找)

简介: 每日一题——寻找右区间(排序 + 二分查找)

寻找右区间(排序 + 二分查找)

题目链接


理解题目

  • 题目给定一个具有n行2列的二维数组intervals,对于intervals每一行元素i,就表示一个区间数组intervals[i][0]即这个区间数组的起始位置startintervals[i][1]就是区间数组的结束位置end。同时,题目告诉我们对于每一个区间数组i,他们的start都不同
  • 题目要我们找的,就是对于每一个区间数组i,寻找一个start满足start >= end,如果存在该start,就要使start最小化,即使start - end的值最小
  • 找到start后,就将这个start的索引记录到返回数组(如果这个start位于第n个区间数组,那么索引就是n - 1),否则记录-1

思路

最简单的思想,就是利用两层循环来求得答案。第一层循环用来遍历每个区间数组intervers[i],第二层循环用来找到每一个intervals[i][start]end,但显然,这个方法的时间复杂度为O(N2),效率低,故不做讨论

应该想到,我们应该对每个区间数组进行排序,以此来优化我们的查找。

需要解决以下几个问题:

  1. 我们应该以每个区间的start为标准还是以end为标准进行排序?
  • 要清楚的一点是,本题我们查找的是符合条件的start,以此来满足start >= intervals[i][start],因此,如果要优化查找start的效率,就应该以start为标准对每个区间数组进行排序
  1. 找到符合条件的start后,要将其所在区间数组的索引记录在返回数组,但是将区间数组排序后,索引值不久变了吗?怎么解决?
  • 我们可以新建一个结构体数组StartNode用来存储每个区间数组的start以及索引index,这样就不会丢失正确定索引了。
typedef struct Node
{
    int start;  //区间数组的start
    int index;  //区间数组的索引
}Node;
int cmp(const void* num1, const void* num2)
{
    return ((Node*)num1)->start - ((Node*)num2)->start;
}
int* findRightInterval(int** intervals, int intervalsSize, int* intervalsColSize, int* returnSize){
    //创建一个结构体数组
    //用来存储每个区间数组的start,及其索引
    Node* StartNode = (Node*)malloc(sizeof(Node) * intervalsSize);
    for (int i = 0; i < intervalsSize; i++)
    {
        StartNode[i].start = intervals[i][0];
        StartNode[i].index = i;
    }
    //对区间数组的start进行升序排序
    qsort(StartNode, intervalsSize, sizeof(Node), cmp);
    ………………
}

解决了这两个问题,就可以开始正式查找了:

利用一层循环遍历每个区间数组的end,接着利用二分查找在StartNode中查找符合条件的start,同时将索引录入返回数组,如果没有找到,就录入-1。

实现代码

/**
 * Note: The returned array must be malloced, assume caller calls free().
 */
typedef struct Node
{
    int start;
    int index;
}Node;
int cmp(const void* num1, const void* num2)
{
    return ((Node*)num1)->start - ((Node*)num2)->start;
}
int* findRightInterval(int** intervals, int intervalsSize, int* intervalsColSize, int* returnSize){
    int row = intervalsSize;
    int col = *intervalsColSize;
    //创建一个结构体数组
    //用来存储每个区间数组的start,及其索引
    Node* StartNode = (Node*)malloc(sizeof(Node) * intervalsSize);
    for (int i = 0; i < intervalsSize; i++)
    {
        StartNode[i].start = intervals[i][0];
        StartNode[i].index = i;
    }
    //对区间数组的start进行升序排序
    qsort(StartNode, intervalsSize, sizeof(Node), cmp);
    int* ret = (int*)malloc(sizeof(int) * intervalsSize);
    *returnSize = intervalsSize;
    //遍历原数组的每一个end
    //同时在已经有序的升序数组中找到第一个大于end的start
    //并将其索引记录到返回数组,如果找不到,就记录为-1
    for (int i = 0; i < intervalsSize; i++)
    {
        int end_i = intervals[i][1];
        int target = -1;  //target即正确的索引位置,初始化为-1代表假定找不到符合条件的start
        //利用二分法找到 start >= end,同时又是最小的start及其索引
        int left = 0;
        int right = intervalsSize - 1;
        while (left <= right)
        {
            int mid = (right - left) / 2 + left;
            if (StartNode[mid].start >= end_i)
            {
                target = StartNode[mid].index;
                right = mid - 1;
            }
            else
                left = mid + 1;
        }
        //将索引录入返回数组
        ret[i] = target;
    }
    //销毁申请的动态内存
    free(StartNode);
    return ret;
}
相关文章
|
3月前
|
消息中间件 数据管理 Serverless
阿里云消息队列 Apache RocketMQ 创新论文入选顶会 ACM FSE 2025
阿里云消息团队基于 Apache RocketMQ 构建 Serverless 消息系统,适配多种主流消息协议(如 RabbitMQ、MQTT 和 Kafka),成功解决了传统中间件在可伸缩性、成本及元数据管理等方面的难题,并据此实现 ApsaraMQ 全系列产品 Serverless 化,助力企业提效降本。
|
8月前
|
并行计算 前端开发 异构计算
告别服务器繁忙,云上部署DeepSeek
本文以 DeepSeek-R1-Distill-Qwen-32B-FP8 为例,向您介绍如何在GPU实例上使用容器来部署量化的 DeepSeek-R1 蒸馏模型。
|
4月前
|
数据安全/隐私保护 Android开发 Windows
2025 年三款免费高清无水印视频录制工具推荐合集
本文介绍了三款免费高清录屏软件:EVCapture、Bandicam 和 屏幕录像机(oCam)。EVCapture 功能强大,支持视频录制与直播,提供分屏录制、实时按键显示等;Bandicam 适合游戏录屏,可自定义录制区域并添加Logo,还支持音频和摄像头设置;oCam 小巧灵活,支持多种视频格式(如GIF、MP4等)及音频、截图功能。三者均无水印,画质清晰,满足不同录屏需求。资源地址已提供,可供下载体验。
3032 0
|
11月前
|
存储 C语言
【c语言】玩转文件操作
本文介绍了C语言中文件操作的基础知识,包括文件的打开和关闭、文件的顺序读写、文件的随机读写以及文件读取结束的判定。详细讲解了`fopen`、`fclose`、`fseek`、`ftell`、`rewind`等函数的使用方法,并通过示例代码展示了如何进行文件的读写操作。最后,还介绍了如何判断文件读取结束的原因,帮助读者更好地理解和应用文件操作技术。
234 2
|
存储 大数据 Python
NumPy 内存管理和性能调优
【8月更文第30天】NumPy 是 Python 中用于科学计算的核心库之一,它提供了高效的数组操作功能。然而,随着数据集的增大,如何有效地管理和优化 NumPy 数组的内存使用成为了一个重要的问题。本文将介绍一些技巧,帮助你更好地管理和优化 NumPy 数组的内存使用。
575 0
|
编解码 人工智能 测试技术
安卓适配性策略:确保应用在不同设备上的兼容性
【4月更文挑战第13天】本文探讨了提升安卓应用兼容性的策略,包括理解平台碎片化、设计响应式UI(使用dp单位,考虑横竖屏)、利用Android SDK的兼容工具(支持库、资源限定符)、编写兼容性代码(运行时权限、设备特性检查)以及优化性能以适应低端设备。适配性是安卓开发的关键,通过这些方法可确保应用在多样化设备上提供一致体验。未来,自动化测试和AI将助力应对设备碎片化挑战。
1662 4
|
Cloud Native 安全 Java
云原生网关MSE-Higress测评报告
MSE-Higress是遵循开源Ingress/Gateway API标准的下一代网关产品,将传统的流量网关、微服务网关、安全网关合三为一,具有高集成、易使用、易扩展、热更新的特点。本报告将从流量调度、服务治理、插件市场等方面对MSE-Higress进行详细测评,并对比其他网关如Nginx、APISIX、Spring Cloud Gateway等,分析其在功能、性能、架构、可扩展性、运维、价格等方面的优势和不足。
876 48
|
Arthas 测试技术
Arthas调试案例:watch案例
Arthas调试案例:watch案例
|
Linux
【Linux命令200例】cksum用于计算文件的校验和
cksum命令是一个用于计算文件的校验和的Linux命令。它通过对文件内容进行CRC(循环冗余校验)计算来生成校验和值。校验和值可以用于验证文件在传输过程中是否被修改或损坏。
913 0
|
人工智能 机器人
AI智能外呼机器人工作流程
AI外呼机器人是集合了自动拨打电话、多轮语音交互、客户意向智能分级、外呼任务自定义等多功能于一体智能语音对话机器人。 一个完整的智能外呼流程(不涉及转人工)包含了四个环节,各环节会由外呼系统整体串联起来进行运作: 1.用户接听:外呼工作流程的开始,外呼系统需识别用户接听信号。 2.客户机器人响应:这一环节关键在策略输出,外呼系统需根据用户应答,识别用户意图或动作,根据机器人预设任务流和策略给出响应话术。 3.用户应答/动作:这一模块主要在外呼系统需对用户的意图和动作进行精准识别,做用户状态记录,以便一下步策略的实施。 4.用户/客服机器人挂机:当机器人走完任务流会主动挂断,或用户提前