力扣-57-插入区间

采用最直接的思路,if-else去考虑每一种情况并做出操作(比如找到新区间左端点落在哪个位置,几种情况,然后再去考虑右端点的几种情况)是非常细致繁琐的,以至于很容易出错

考虑三种情况,新区间的两个端点:

  1. 分别落在两个原有的区间中:保留前一个区间的左端点和后一个区间的右端点,将他俩合并成一个新的区间
  2. 只有一个端点落在了某个区间:以左端点落在了某个区间为例,就将区间左端点和新区间的右端点合并为一个区间
  3. 两个端点没有落在任何区间:直接插入作为新的区间成员

另外需要考虑到的是:以上合并的情况中,所有被新合并区间所包含的区间全部都需要删除

编码

  1. 我需要知道这两个端点有没有落在区间中,如果有,做右端点又分别是谁

需要额外仔细考虑的是各个等于的情况

class Solution {
public:
vector<vector<int>> insert(vector<vector<int>>& intervals, vector<int>& newInterval) {
int len = intervals.size();
// 首先确定左端点是否落在了某个区间中
for (int i = 0; i < len; i++) {
if (intervals[i][1] >= newInterval[0] && intervals[i][0] <= newInterval[0]) {
// 新区间的左端点落在某个区间中
// 不管右端点怎么样,新区间的左端点都会被合并
// 然后去找右端点
for (int j = i + 1; j < len; j++) {
if (newInterval[1] > intervals[j][1])intervals.erase(intervals.begin() + j);
else if (newInterval[1] >= intervals[j][0]) {
// 右端点落在了某个区间中
intervals[i][1] = intervals[j][1];// 合并新区间
break;
}
// 如果右端点比任何一个区间都大
if (j == len - 1) intervals[i][1] = newInterval[1];
}
break;
}
else if (intervals[i][0] > newInterval[0]) {
// 说明确定了左端点没有落在任何一个区间中
// 判断确定了第一个大于左端点的区间,因为右端点一定大于左端点,所以可以接着遍历
for (int j = i + 1; j < len; j++) {
// 如果区间右端点小于新区间右端点,会被合并后的区间覆盖
if (intervals[j][1] < newInterval[1]) intervals.erase(intervals.begin() + j);
if (newInterval[1] <= intervals[j][1] && newInterval[1] >= intervals[j][0]) {
// 右端点落在了某个区间中(相等的情况没有被删除)
intervals[j][0] = newInterval[0];
break;
}
// 右端点也没有落在任何区间
if (j == len - 1) intervals.push_back(newInterval);
}
break;
}
}
return intervals;
}
};

这一版的代码犯了很大一个错误——我不能一遍遍历数组一遍删除数组(好吧我还尝试了知错不改邪魔外道尝试去修改指针)
其实就想剩下额外的空间,不想再准备一个二维数组去存放结果


class Solution {
public:
vector<vector<int>> insert(vector<vector<int>>& intervals, vector<int>& newInterval) {
int len = intervals.size();
if (!len) return { newInterval };
vector<vector<int>>res;
// 首先确定左端点是否落在了某个区间中
for (int i = 0; i < len; i++) {
if (intervals[i][1] >= newInterval[0] && intervals[i][0] <= newInterval[0]) {
// 新区间的左端点落在某个区间中
// 不管右端点怎么样,新区间的左端点都会被合并
// 然后去找右端点
for (int j = i; j < len; j++) {
if (intervals[j][0] > newInterval[1] || j == len - 1) {
// 右端点不在任何一个区间内
res.back()[1] = newInterval[1];
res.push_back(intervals[j]);
break;
}
if (newInterval[1] <= intervals[j][1] || intervals[j][0] <= newInterval[1]) {
// 右端点落在了某个区间中
intervals[i][1] = intervals[j][1];// 合并新区间
res.push_back(intervals[i]);
}
}
break;
}
else if (intervals[i][0] > newInterval[0]) {
// 说明确定了左端点没有落在任何一个区间中
// 判断确定了第一个大于左端点的区间,因为右端点一定大于左端点,所以可以接着遍历
for (int j = i; j < len; j++) {
if (newInterval[1] <= intervals[j][1] && intervals[j][0] <= newInterval[1]) {
// 右端点落在了某个区间中(相等的情况没有被删除)
intervals[j][0] = newInterval[0];
res.push_back(intervals[j]);
}
if (intervals[j][0] > newInterval[1]) res.push_back(intervals[j]);
else if (j == len - 1)(res.back()[1] = newInterval[1]);
}
break;
}
else {
// 首先左端点没有在任何一个区间,其次左端点不在区间左边,左端点在区间右边
res.push_back(intervals[i]);
}
}
return res;
}
};

昨天尝试未果,沿用上面的思路其实具体实现起来仍旧是老路子,比如:遍历确定左端点位置就要分四种情况:

  1. 左端点在所有区间前面
  2. 左端点在中间,但是没有落在任何一个区间中
  3. 左端点在中间且落在了某个区间中
  4. 左端点在所有区间后面

这样写需要在遍历中嵌套两个相似的遍历,同时还要两个端点各分四种情况,还有取不取等的情况,过于繁琐细致了

官解给出的方法是排序

官解排序

官方题解思路的出发点是:按照所有区间的左端点排序,能够合并的区间一定是连续的

怎么证明暂且不研究,排序然后呢?然后遍历排序后的数组,看能不能合并

class Solution {
public:
vector<vector<int>> insert(vector<vector<int>>& intervals, vector<int>& newInterval) {
// 官方题解思路的出发点是:按照所有区间的左端点排序,能够合并的区间一定是连续的
// 因为只有一个插入数组,所以其实不用真的排一轮
// 好吧,排一轮也可以
int len = intervals.size();
if (!len) return { newInterval };// 如果原二维数组空,直接返回新区间
vector<vector<int>> res;
intervals.push_back(newInterval);
sort(intervals.begin(), intervals.end());
// 比较两个区间能不能合并(感觉有点冒泡两两比较的味儿了)
for (int i = 1; i < len+1; i++) {
// 有几种情况?
// 1. 不能合并,两个独立的区间
// 2. 可以部分合并,就是相交
// 3. 包含
if (intervals[i - 1][1] > intervals[i][1]) {
// 包含
intervals[i][0] = intervals[i - 1][0];
intervals[i][1] = intervals[i - 1][1];
}
else {
if (intervals[i - 1][1] >= intervals[i][0]) {
// 相交
intervals[i][0] = intervals[i - 1][0];
}
else {
// 不相关
res.push_back(intervals[i - 1]);
}
}
}
res.push_back(intervals.back());// 清空,处理最后一个
return res;
}
};

看看能不能优化一下
如果哪里可以优化应该优化我觉得时间会是去掉排序,空间是直接用原数组😂然后看起来又是最开始的老路子
就这样吧,溜了溜了

本文作者:YaosGHC

本文链接:https://www.cnblogs.com/yaocy/p/17070308.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   YaosGHC  阅读(21)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
💬
评论
📌
收藏
💗
关注
👍
推荐
🚀
回顶
收起