首页 > 其他分享 >区间集合:高效解决无重叠区间问题【贪心、区间集合】

区间集合:高效解决无重叠区间问题【贪心、区间集合】

时间:2024-11-01 09:19:44浏览次数:3  
标签:end 重叠 current 集合 移除 区间 排序 贪心

无重叠区间问题的深入解析与C++实现

题目理解

在无重叠区间问题中,我们被给定一个区间集合 intervals,其中每个区间以 [start, end] 的形式表示。我们的目标是确定最少需要移除多少个区间,以确保剩下的区间互不重叠。值得注意的是,当两个区间仅在一个点上接触时(例如 [1, 2][2, 3]),它们被视为不重叠。

题目链接:435. 无重叠区间 - 力扣(LeetCode)

思考过程

1. 排序区间

处理该问题的第一步是对所有的区间按结束时间进行排序。选择结束时间的原因在于,如果我们能够优先保留结束时间较早的区间,就可以为后续可能的区间留出更多的空间。这个策略的本质是利用贪心算法思想:在每一步都选择局部最优解,以期望最终达到全局最优解。

2. 遍历并判断重叠

在对区间进行排序后,我们需要维护一个变量 current_end,表示当前不重叠区间的结束时间。初始化时,current_end 设置为负无穷。在遍历排序后的区间时,我们会执行以下步骤:

  • 对于每一个区间,检查其起始时间是否大于或等于 current_end
    • 无重叠:如果条件满足,说明当前区间可以被保留,随后更新 current_end 为当前区间的结束时间。
    • 重叠:如果不满足条件,则表示存在重叠,此时我们需要增加移除计数器。为了尽量保留更多的区间,我们选择移除结束时间较晚的那个区间。

3. 统计移除次数

每当我们发现需要移除一个区间时,计数器 count 增加一。最终,遍历完所有区间后,count 的值即为需要移除的最小区间数量。

C++实现

以下是用C++实现的代码:

#include <vector>
#include <algorithm>

using namespace std;

class Solution {
public:
    int eraseOverlapIntervals(vector<vector<int>>& intervals) {
        if (intervals.empty()) return 0;

        // 按结束时间排序
        sort(intervals.begin(), intervals.end(), [](const vector<int>& a, const vector<int>& b) {
            return a[1] < b[1];
        });

        int count = 0;          // 需要移除的区间数量
        int current_end = intervals[0][1]; // 初始化为第一个区间的结束时间

        // 从第二个区间开始遍历
        for (int i = 1; i < intervals.size(); ++i) {
            // 如果当前区间的起始时间小于当前的结束时间,说明重叠了
            if (intervals[i][0] < current_end) {
                count++; // 需要移除一个区间
            } else {
                // 没有重叠,更新当前结束时间
                current_end = intervals[i][1];
            }
        }

        return count;
    }
};

示例解释

  1. 示例 1

    • 输入: [[1,2],[2,3],[3,4],[1,3]]
    • 排序后的区间: [[1,2],[1,3],[2,3],[3,4]]
    • 遍历过程:
      • 保留 [1,2],更新 current_end2
      • [1,3] 的起始时间 1 小于 current_end 2,计数加一。
      • 保留 [2,3],更新 current_end3
      • 保留 [3,4],更新 current_end4
    • 输出: 1(移除 [1,3]
  2. 示例 2

    • 输入: [[1,2], [1,2], [1,2]]
    • 排序后不变,所有区间相同。
    • 遍历过程:
      • 保留第一个 [1,2],更新 current_end
      • 后面的两个 [1,2] 都重叠,计数加二。
    • 输出: 2(移除两个 [1,2]
  3. 示例 3

    • 输入: [[1,2], [2,3]]
    • 排序后不变,两个区间不重叠。
    • 遍历过程:
      • 保留第一个 [1,2],更新 current_end
      • [2,3] 的起始时间 2 不小于 current_end,继续。
    • 输出: 0(不需要移除任何区间)

复杂度分析

  • 时间复杂度:O(n log n),主要来自于对区间的排序。排序的时间复杂度是 O(n log n),遍历的时间复杂度是 O(n),整体以排序为主。
  • 空间复杂度:O(1),只使用了常数额外空间来存储变量。排序过程中会使用 O(n) 的空间,但在这里我们只考虑算法本身使用的额外空间。

代码的可扩展性

虽然当前实现已经能有效解决问题,但我们可以考虑以下几种扩展:

  1. 输入验证:可以增加对输入有效性的检查,比如判断区间的起始时间是否小于结束时间。
  2. 支持多种数据结构:将函数修改为支持其他数据结构,例如链表或自定义的区间类,以提高灵活性。
  3. 返回移除的区间:除了返回移除的数量,还可以修改代码,使其返回具体需要移除的区间,以便于用户了解具体情况。

总结

通过对区间的排序和遍历,我们能够高效地解决无重叠区间的问题。利用贪心算法的策略,保持当前的结束时间来判断是否重叠,使得我们的解决方案简单而有效。这种方法适用于大规模输入,能够在合理的时间内得出结果。希望这篇解析能帮助读者更好地理解和实现无重叠区间的问题,提升编程和算法思维能力。

标签:end,重叠,current,集合,移除,区间,排序,贪心
From: https://blog.csdn.net/qq_22841387/article/details/143423358

相关文章

  • python基础(集合)
    学习目标:集合的概念,创建,增加元素,移除元素,运算(交集,并集,差集,对称差集),推导式一.集合的概念:Python中的集合(set)是一种无序、无重复元素的数据结构,它的元素是不可变的(可哈希的)集合是由大括号{}包围的元素集合如果定义空集合,即不包含任何元素,必须使用set()函数定义二.集合的创建......
  • 区间和---使用离散化
    假定有一个无限长的数轴,数轴上每个坐标上的数都是0。现在,我们首先进行n次操作,每次操作将某一位置x上的数加c。接下来,进行m次询问,每个询问包含两个整数l和r,你需要求出在区间[l,r]之间的所有数的和。#include<iostream>#include<vector>#include<algorithm>usingn......
  • NOIP2024集训Day65 贪心
    NOIP2024集训Day65贪心A.[NOI2015]荷马史诗简化题意,即构造一颗\(k\)叉树,每个节点的权值为其所有孩子的权值之和,给定的\(n\)个数必须使用,其余空缺处用\(0\)补全。考虑使用优先队列,首先弹入\(n+(n-1)\%(k-1)\)个元素(不足处用0代替),然后每次弹出前\(k\)小的数......
  • 集合竞价逐笔数据,level2行情接口统计验证
    最近做集合竞价的策略,用的level2数据。集合竞价阶段推送数据量很大,但是不确定有没有因为网络原因的数据纰漏,所以需要验证一下。把今天所有的数据记录了日志,其中筛选了09:25集合竞价的推送:grep'2024/07/2909:25'quotes.log|greplv2level2行情结果如下:2024/07/2909:......
  • 贪心
    原理通过证明局部最优解可以得出全局最优解,从而\(O(n)\)解决问题。常用数学归纳法证明贪心正确性。模板取\(x,y\),计算\(f(x\text{先于}y),f(y\text{先于}x)\),令\(f(x\text{先于}y)>f(y\text{先于}x)\),解出贪心公式。区间类区间覆盖选取尽量少的区间使得区间[s......
  • MongoDB关联另一个集合
    MongoDB本身并不支持传统关系数据库中的外键(foreignkey)概念,因为它是一个文档数据库,数据通常是以JSON格式存储的文档,并且不强制要求文档之间的关系。然而,你可以通过以下几种方式在MongoDB中实现类似外键的功能:1.引用(References)你可以在一个文档中存储另一个文档的ID,从而......
  • Day65 小贪心 & 自选杂题
    哎怎么必可公益赛被爆破了,怎么lifan还加了几道我们的训练题目作为补偿。CF不知道死了多久了,一上午都没有打成duel!今天上午精神状态明显好了很多,可能和咖啡有点关系吧。按照时间顺序写题吧。AT_arc070_b可以进行撤销背包,也可以算前后缀背包,都是记录方案数。不难的。AT_a......
  • 刷题总结——区间和
    前缀和前缀和是一种解决区间求和问题的辅助方法,前缀和只适用于固定区间(数组、树等),如果区间元素发生变化,则不适用,此时需要考虑树状数组、线段树等方式。问题类型常见的问题也是和DP一样,求最大/最小/方案数。类型题目备注前缀和+哈希LC560两数之和思路前缀和+......
  • Go语言内置集合的隐式指针
    在Go语言中,有几种内置集合类型(如slice、map和channel),这些类型的特殊之处在于它们实际上是隐式指针。这意味着当我们将这些集合类型传递给函数或方法时,传递的是它们的引用,而不是拷贝。这种特性使得这些集合能够在函数中直接修改原始数据,而不需要显式传递指针。1.内置集合......
  • 华为OD机试 E卷|商人买卖 /贪心的商人
    华为OD机试E卷|商人买卖or贪心的商人0、关于本专栏&刷题交流群本文收录于专栏【2024华为OD机试真题】,专栏共有上千道OD机试真题,包含详细解答思路、与四种代码实现(Python、Java、C++、JavaScript)。点击文末链接加入【华为OD机试交流群】,和群友一起刷题备考。刷的越多,考试中遇......