2021.8.9 力扣-合并区间

目录

题目链接

题目描述

方法一

方法二

方法三


题目链接

56. 合并区间 - 力扣(LeetCode)

题目描述

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

方法一

class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        vector<vector<int>> ans;
        sort(intervals.begin(), intervals.end());       //将各行按首元素排序
        int left, right;        //表示区间的左边界和右边界
        for (int i = 0; i < intervals.size(); i++)
        {
            left = intervals[i][0];
            right = intervals[i][1];
            int j;
            for (j = i + 1; j < intervals.size(); j++)
            //在该循环中寻找是否有能够合并的区间
            {
                if (right < intervals[j][0])
                //如果目前的右边界小于该区间的左边界,说明合并不了,退出
                {
                    j--;
                    break;
                }
                if (right >= intervals[j][1] && j+1<intervals.size())
                //如果目前的右边界大于等于该区间的右边界,说明该区间包含于[left,right]中,继续判断下一个区间(如果存在)
                {
                    continue;
                }
                if (right >= intervals[j][0] && right < intervals[j][1])
                //如果目前的右边界大于等于该区间的左边界,但小于其右边界,合并
                {
                    right = intervals[j][1];
                }
            }
            i = j;    //跳过已经判断完的区间
            ans.push_back({ left , right });
        }
        return ans;
    }
};

其中sort函数作用于二维数组vector的效果是,将vector各行按照首元素从小到大排序。

虽然该方法使用了两层的for循环,但实际上数组intervals中的各个区间只遍历了一次,由于使用了sort函数,时间复杂度为O(nlogn)。

方法二

class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        vector<vector<int>> ans;
        sort(intervals.begin(), intervals.end());       //将各行按首元素排序
        int left, right;        //表示区间的左边界和右边界
        for (int i = 0; i < intervals.size(); i++)
        {
            left = intervals[i][0];
            right = intervals[i][1];
            if (!ans.size() || ans.back()[1] < left)
            //如果该区间的左边界比ans中最后一个区间的右边界还大,则插入该区间
            {
                ans.push_back({ left , right });
            }
            else
            //否则,合并两个区间,即选择一个最大的右边界作为ans中最后一个区间的右边界
            {
                ans.back()[1] = max( ans.back()[1] , right );
            }
        }
        return ans;
    }
};

官方的题解看起来还是赏心悦目!虽然和我的方法在复杂度上是一样的,但是代码却更加简洁明了,省去了方法一中较繁琐的条件判断。

方法三

class Solution {
public:
    vector<vector<int>> merge(vector<vector<int>>& intervals) {
        sort(intervals.begin(), intervals.end());
        vector<vector<int>> ans;
        //left和right表示在正在合并的区间的左右边界
        int left = intervals[0][0], right = intervals[0][1];
        for (int i = 1; i < intervals.size(); i++)
        {
            int curleft = intervals[i][0], curright = intervals[i][1];
            //如果当前这个区间的左边界位于正在合并的区间的左右边界内,则选出right和curright中的最大值作为新的右边界
            if (left <= curleft && curleft <= right) right = max(right, curright);
            //否则说明当前的这个区间已经无法合并到区间[left,right]中了
            else
            {
                ans.push_back({left, right});    //将区间[left,right]加入ans中
                //重新开始下一轮判断
                left = curleft;
                right = curright;
            }
        }
        ans.push_back({left, right});    //别忘了最后一个区间
        return ans;
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值