代码训练LeetCode(49)插入区间
代码训练(49)插入区间
Author: Once Day Date: 2025年10月25日
漫漫长路,才刚刚开始…
全系列文章可参考专栏: 十年代码训练_Once-Day的博客-CSDN博客
参考文章:
- 57. 插入区间 - 力扣(LeetCode)
- 力扣 (LeetCode) 全球极客挚爱的技术成长平台
文章目录
- 代码训练(49)插入区间
- 1. 原题
- 2. 分析
- 3. 代码实现
- 4. 总结
1. 原题
给你一个 无重叠的 ,按照区间起始端点排序的区间列表
intervals,其中intervals[i] = [starti, endi]表示第i个区间的开始和结束,并且intervals按照starti升序排列。同样给定一个区间newInterval = [start, end]表示另一个区间的开始和结束。在
intervals中插入区间newInterval,使得intervals依然按照starti升序排列,且区间之间不重叠(如果有必要的话,可以合并区间)。返回插入之后的
intervals。注意 你不需要原地修改
intervals。你可以创建一个新数组然后返回它。提示:
0 <= intervals.length <= 104intervals[i].length == 20 <= starti <= endi <= 105intervals根据starti按 升序 排列newInterval.length == 20 <= start <= end <= 105
示例 1:
输入:intervals = [[1,3],[6,9]], newInterval = [2,5]
输出:[[1,5],[6,9]]
示例 2:
输入:intervals = [[1,2],[3,5],[6,7],[8,10],[12,16]], newInterval = [4,8]
输出:[[1,2],[3,10],[12,16]]
解释:这是因为新的区间 [4,8] 与 [3,5],[6,7],[8,10] 重叠。
2. 分析
给定一个已经按照起始端点从小到大排列的区间列表 intervals,每个区间表示为 [starti, endi]。同时给定一个新的区间 newInterval,需要将这个新区间插入到列表中,插入后仍需保持区间列表的有序性,并且要合并所有重叠的区间。
这个问题主要考察如何有效地处理区间的插入和合并。因为原列表已经根据起始点排序,我们可以利用这一特性来优化插入过程。
解题思路:
- 初始化变量:创建一个新的列表
result来保存最终的区间序列。 - 遍历原区间列表:对于列表
intervals中的每一个区间:- 无重叠且在新区间前:如果当前区间在新区间的左侧且没有重叠,直接将其加入到
result。 - 无重叠且在新区间后:如果当前区间在新区间的右侧且没有重叠,说明新区间已经插入完毕,可以将新区间和后续的区间加入
result。 - 重叠区间:如果当前区间与新区间有重叠,合并两个区间的边界,形成一个新的合并区间。
- 无重叠且在新区间前:如果当前区间在新区间的左侧且没有重叠,直接将其加入到
- 处理未插入的新区间:如果循环结束后新区间还未插入,将其添加到
result的末尾。
分析步骤:
- 遍历每个区间,判断是否重叠。
- 根据重叠情况更新新区间的起点和终点。
- 将不重叠的区间加入结果列表。
- 最后,确保所有区间都被处理。
性能优化关键点:
- 空间优化:使用动态数组来避免过多的内存分配。
- 时间优化:利用区间已排序的特性,通过一次遍历完成插入和合并,避免多次迭代。
3. 代码实现
#include <stdio.h>
#include <stdlib.h>// 结构体定义区间
typedef struct {int start;int end;
} Interval;// 动态数组结构体来存储区间序列
typedef struct {Interval* intervals;int size;int capacity;
} IntervalList;// 初始化区间列表
IntervalList* createIntervalList() {IntervalList* list = (IntervalList*)malloc(sizeof(IntervalList));list->intervals = (Interval*)malloc(10 * sizeof(Interval)); // 初始容量为10list->size = 0;list->capacity = 10;return list;
}// 动态扩展数组
void resizeIntervalList(IntervalList* list) {int newCapacity = list->capacity * 2;Interval* newIntervals = (Interval*)realloc(list->intervals, newCapacity * sizeof(Interval));if (newIntervals) {list->intervals = newIntervals;list->capacity = newCapacity;}
}// 添加区间到列表
void addInterval(IntervalList* list, Interval newInterval) {if (list->size == list->capacity) {resizeIntervalList(list);}list->intervals[list->size++] = newInterval;
}/*** 插入并合并区间* @param intervals 二维数组,表示已有的区间列表* @param intervalsSize 区间列表的大小* @param intervalsColSize 每个区间的大小(始终为2)* @param newInterval 要插入的新区间* @param newIntervalSize 新区间的大小(始终为2)* @param returnSize 返回的区间数量* @param returnColumnSizes 每个返回区间的大小数组(每个元素应为2)* @return 返回合并后的区间列表*/
int** insert(int** intervals, int intervalsSize, int* intervalsColSize, int* newInterval, int newIntervalSize, int* returnSize, int** returnColumnSizes) {// 初始化结果数组int** result = (int**)malloc((intervalsSize + 1) * sizeof(int*));*returnColumnSizes = (int*)malloc((intervalsSize + 1) * sizeof(int));int resultSize = 0;int i = 0;// 添加所有在新区间左侧且不重叠的区间while (i < intervalsSize && intervals[i][1] < newInterval[0]) {result[resultSize] = (int*)malloc(2 * sizeof(int));result[resultSize][0] = intervals[i][0];result[resultSize][1] = intervals[i][1];(*returnColumnSizes)[resultSize] = 2;resultSize++;i++;}// 合并所有与新区间重叠的区间while (i < intervalsSize && intervals[i][0] <= newInterval[1]) {newInterval[0] = newInterval[0] < intervals[i][0] ? newInterval[0] : intervals[i][0];newInterval[1] = newInterval[1] > intervals[i][1] ? newInterval[1] : intervals[i][1];i++;}result[resultSize] = (int*)malloc(2 * sizeof(int));result[resultSize][0] = newInterval[0];result[resultSize][1] = newInterval[1];(*returnColumnSizes)[resultSize] = 2;resultSize++;// 添加所有在新区间右侧且不重叠的区间while (i < intervalsSize) {result[resultSize] = (int*)malloc(2 * sizeof(int));result[resultSize][0] = intervals[i][0];result[resultSize][1] = intervals[i][1];(*returnColumnSizes)[resultSize] = 2;resultSize++;i++;}*returnSize = resultSize;return result;
}int main() {// 示例int intervalsSize = 5;int intervalsColSize[] = {2, 2, 2, 2, 2};int** intervals = (int**)malloc(intervalsSize * sizeof(int*));for (int i = 0; i < intervalsSize; i++) {intervals[i] = (int*)malloc(2 * sizeof(int));}intervals[0][0] = 1; intervals[0][1] = 2;intervals[1][0] = 3; intervals[1][1] = 5;intervals[2][0] = 6; intervals[2][1] = 7;intervals[3][0] = 8; intervals[3][1] = 10;intervals[4][0] = 12; intervals[4][1] = 16;int newInterval[] = {4, 8};int newIntervalSize = 2;int returnSize;int* returnColumnSizes;int** mergedIntervals = insert(intervals, intervalsSize, intervalsColSize, newInterval, newIntervalSize, &returnSize, &returnColumnSizes);// 打印结果for (int i = 0; i < returnSize; i++) {printf("[%d, %d] ", mergedIntervals[i][0], mergedIntervals[i][1]);}printf("\n");return 0;
}
4. 总结
这个问题是一个很好的练习,用于理解和操作区间数据。通过这个题目,我们可以学习到如何高效地合并数据范围,并且对动态数组的操作有更深的理解。对于提升编程能力,关键是掌握数据结构的选择和对算法效率的考量。
