[力扣c++实现] 56. 合并区间

本文介绍了一种C++实现的解决方案,用于合并重叠的区间。首先对区间按起始边界排序,然后逐个检查相邻区间,通过自定义的merge2vec函数判断并合并相邻的交叠区间。在合并过程中,将已合并的区间标记为废弃,最后返回未废弃的不重叠区间。这种方法在一次遍历中完成了区间合并,避免了重复计算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

56. 合并区间

难度中等1214

以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] = [starti, endi] 。请你合并所有重叠的区间,并返回一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间。

示例 1:

输入:intervals = [[1,3],[2,6],[8,10],[15,18]]
输出:[[1,6],[8,10],[15,18]]
解释:区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].

示例 2:

输入:intervals = [[1,4],[4,5]]
输出:[[1,5]]
解释:区间 [1,4] 和 [4,5] 可被视为重叠区间。

提示:

  • 1 <= intervals.length <= 104
  • intervals[i].length == 2
  • 0 <= starti <= endi <= 104

1.c++

/*
* 2021-12-5 22:15 
* Hangzhou
*
*/

#include <vector>
#include <algorithm>
#include <iostream>

using namespace std;

class Solution {
public:
    bool merge2vec(vector<int>& vec1,vector<int>& vec2)
    {
        if (vec2[0] > vec1[1])
        {
            return false;
        }
        else if (vec2[0] <= vec1[1] && vec2[1] > vec1[1])
        {
            vec2[0] = vec1[0];
            return true;
        }
        else if (vec1[0] >= vec2[0] && vec1[1] >= vec2[1])
        {
            vec2[0] = vec1[0];
            vec2[1] = vec1[1];
            return true;
        }
        return false;
    }

    vector<vector<int>> merge(vector<vector<int>>& intervals) 
    {
        vector<vector<int>> ret;
        //将各区间按照边界(第一个元素)从小到大排序
        std::sort(intervals.begin(),intervals.end(),[](std::vector<int> &pre,std::vector<int> &next)->bool 
        {
            return pre[0] < next[0];
        });

        int size = intervals.size();

        //将排序后的区间从左到右进行合并
        bool bad_vec[size] = {false};
        int i = 0;
        while (i < size - 1)
        {
            auto &first_vec = intervals[i];
            auto &second_vec = intervals[i+1];

            if (true == merge2vec(first_vec,second_vec))
            {
                bad_vec[i] = true;
            }
            ++i;
        }
        for (int i = 0; i < size;++i)
        {
          if (bad_vec[i] == false)
          {
            ret.push_back(intervals[i]);
          }
        }

        return ret;
    }
};

template<class T>
void print_sequence(T &container)
{
  for (auto &elem:container)
  {
    for (auto &e:elem)
    {
        std::cout<<e << std::endl;
    }
    std::cout<<"--------------"<<std::endl;
  }
}

int main()
{
  Solution slu;
  std::vector<std::vector<int>> vec_2 = {{1,3},{2,6},{8,10},{15,18}};
  auto ret = slu.merge(vec_2);
  print_sequence(ret);
  return 0;
}

2.思路讲解:

(1) 区间合并的标准是区间存在交集或包含关系,为了更好地找到各个区间的交集关系,所以我们先将各区间按照其start边界从小到大地排序。

如原始输入:

intervals = [[1,3],[15,18],[8,10],[2,6]]

按照区间的start排序后变为:

intervals = [[1,3],[2,6],[8,10],[15,18]]

(2) 排序后,相邻两区间的关系就只可能是如下三种:

在这里插入图片描述

这就是我们在使用函数bool merge2vec(vector<int>& vec1,vector<int>& vec2)合并区间vec1、vec2时它俩之间可能的关系。

于是我们在不同的情况分支进行合并((1)、(2)、(3)), 此时,只有条件(2)、(3)这两种情况需要合并

(3)关键点

​ a) 为了能够在一趟扫描(O(n)) 的过程中就能合并所有的区间,如果相邻区间A、B需要合并,那么我们通过修改B的边界值,将其变为合并后的新区间,这样在++i后就可以合理且正确进行下一次的相邻区间B、C的合并。

​ b) 当相邻区间A、B合并且置B区间为新区间后,后续从当前的区间组合中返回最终的结果。A区间就应该不再采用,所以在发生合并后我们应该将A区间置为废弃。

if (true == merge2vec(first_vec,second_vec))//发生合并
{
    bad_vec[i] = true;
}

(4)在完成合并过程后,返回新的区间组合。

即从intervals区间组合中,将那些未被标记为废弃的区间取出来插入到新区间,返回。

for (int i = 0; i < size;++i)
{
    if (bad_vec[i] == false)
    {
        ret.push_back(intervals[i]);
    }
}
好的,我很乐意为您解释力扣56题"合并区间"的Python解法。 力扣56题"合并区间"是一个经典的区间问题。题目要求我们将一个包含多个重叠区间的列表合并成不重叠的区间列表。 以下是一个Python解法: ```python class Solution: def merge(self, intervals: List[List[int]]) -> List[List[int]]: # 首先按区间的起始位置排序 intervals.sort(key=lambda x: x[0]) merged = [] for interval in intervals: # 如果当前区间与结果列表中的最后一个区间不重叠,直接添加 if not merged or merged[-1][1] < interval[0]: merged.append(interval) else: # 否则,有重叠,更新结果列表中最后一个区间的结束位置 merged[-1][1] = max(merged[-1][1], interval[1]) return merged ``` 这个解法的主要步骤如下: 1. 首先,我们按每个区间的起始位置对输入的区间列表进行排序。 2. 然后,我们初始化一个空的合并结果列表。 3. 我们遍历排序后的区间列表: - 如果当前区间与结果列表中的最后一个区间不重叠,我们就直接将当前区间添加到结果列表中。 - 如果有重叠,我们就更新结果列表中最后一个区间的结束位置为当前区间和原最后一个区间结束位置的最大值。 4. 最后,我们返回合并后的结果列表。 这个算法的时间复杂度是O(n log n),其中n是区间的数量,主要是因为我们进行了排序操作。空间复杂度是O(n),用于存储结果。 这个解法的高效之处在于通过排序简化了重叠区间的判断过程,使得我们只需要比较结果列表中的最后一个区间和当前区间就可以决定如何处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值