LeeCode 57. 插入区间

给你一个无重叠的 按照区间起始端点排序的区间列表 intervals,其中 intervals[i] = [starti, endi] 表示第 i 个区间的开始和结束,并且 intervals 按照 starti 升序排列。同样给定一个区间 newInterval = [start, end] 表示另一个区间的开始和结束。

intervals 中插入区间 newInterval,使得 intervals 依然按照 starti 升序排列,且区间之间不重叠(如果有必要的话,可以合并区间)。

返回插入之后的 intervals

注意 你不需要原地修改 intervals。你可以创建一个新数组然后返回它。

示例 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] 重叠。

提示:

  • 0 <= intervals.length <= 104
  • intervals[i].length == 2
  • 0 <= starti <= endi <= 105
  • intervals 根据 starti升序 排列
  • newInterval.length == 2
  • 0 <= start <= end <= 105

答案:

cpp 复制代码
#define MAX_VAL(a, b) (a > b ? a : b)
#define MIN_VAL(a, b) (a < b ? a : b) 

// leecode 57.插入区间
int** insert(int** intervals, int intervalsSize, int* intervalsColSize, int* newInterval, int newIntervalSize, int* returnSize, int** returnColumnSizes) {
	// 方案1: 将要插入的区间直接加到数组中,再给区间排序,再合并区间
	// 方案2: 因为给出的区间数组已经是升序的了,只需要将要插入的区间依次和数组中区间对比,有重合则合并区间, 无重复则在合适的时机插入新区间。
	// 使用方案2:

	*returnSize = 0; // 返回新的二维数组的长度,即区间个数,后面更新数组时动态修改其大小。 

	int** res = (int**)malloc(sizeof(int*) * (intervalsSize + 1)); // 最多需要这么大内存空间
	if (!res) {
		fprintf(stderr, "Failed to malloc!\n");
		exit(EXIT_FAILURE);
	}

	// returnColumnSizes 标识返回的二维数组中,每个一维数组的长度
	*returnColumnSizes = (int*)malloc(sizeof(int*) * (intervalsSize + 1)); // 最多需求这么多内存
	if (!(*returnColumnSizes)) {
		fprintf(stderr, "Failed to malloc!\n");
		exit(EXIT_FAILURE);
	}

	// 遍历数组,合并区间, 并在合适的时机插入区间
	int left = newInterval[0];
	int right = newInterval[1];
	bool insert = false; // 目标区间是否已插入
	for (int i = 0; i < intervalsSize; i++) {
		int* interval = *(intervals + i); // 或者这样写int* interval = intervals[i];
		if (insert) {
			// 目标区间已插入了,只需要加入原有区间
			int* interval_ = (int*)malloc(sizeof(int) * 2);
			if (!interval_) {
				fprintf(stderr, "Failed to malloc!\n");
				exit(EXIT_FAILURE);
			}
			memcpy(interval_, interval, sizeof(int) * 2);
			(*returnColumnSizes)[*returnSize] = 2; // returnColumnSizes标识返回的二维数组中,每个一维数组的长度,每个一维数组长度为2
			res[(*returnSize)++] = interval_;
			continue;
		}

		if (right < interval[0]) {
			// 不重合,此时不能合并区间,插入该区间
			insert = true;
			int* newInterval_ = (int*)malloc(sizeof(int) * 2);
			if (!newInterval_) {
				fprintf(stderr, "Failed to malloc!\n");
				exit(EXIT_FAILURE);
			}
			newInterval_[0] = left;
			newInterval_[1] = right;
			(*returnColumnSizes)[*returnSize] = 2;
			res[(*returnSize)++] = newInterval_;

			// 原区间还是要加入结果集。
			// 这里直接复制上面那一块代码了。
			int* interval_ = (int*)malloc(sizeof(int) * 2);
			if (!interval_) {
				fprintf(stderr, "Failed to malloc!\n");
				exit(EXIT_FAILURE);
			}
			memcpy(interval_, interval, sizeof(int) * 2);
			(*returnColumnSizes)[*returnSize] = 2; // returnColumnSizes标识返回的二维数组中,每个一维数组的长度,每个一维数组长度为2
			res[(*returnSize)++] = interval_;
		}
		else if (left > interval[1]) {
			// 不重合, 还不能插入,只需要加入原有区间
			int* interval_ = (int*)malloc(sizeof(int) * 2);
			if (!interval_) {
				fprintf(stderr, "Failed to malloc!\n");
				exit(EXIT_FAILURE);
			}
			memcpy(interval_, interval, sizeof(int) * 2);
			(*returnColumnSizes)[*returnSize] = 2; // returnColumnSizes标识返回的二维数组中,每个一维数组的长度,每个一维数组长度为2
			res[(*returnSize)++] = interval_;
		}
		else {
			// 区间有重合, 和当前区间合并为一个更大区间, 更新该区间范围
			left = MIN_VAL(interval[0], left);
			right = MAX_VAL(interval[1], right);
		}
	}
	
	// 最后还需判断是否插入了,未插入说明该区间应该插入到最后
	if (!insert) {
		int* newInterval_ = (int*)malloc(sizeof(int) * 2);
		if (!newInterval_) {
			fprintf(stderr, "Failed to malloc!\n");
			exit(EXIT_FAILURE);
		}
		newInterval_[0] = left;
		newInterval_[1] = right;
		(*returnColumnSizes)[*returnSize] = 2;
		res[(*returnSize)++] = newInterval_;
	}

	return res;
}

测试代码:

cpp 复制代码
void testLeeCode57() {
	int arr1[] = {1, 3};
	int arr2[] = {6, 9};
	int* intervals[] = { arr1, arr2}; // intervals为int*数组,所以其类型则为int** 
	int intervalsSize = sizeof(intervals) / sizeof(intervals[0]);
	int* intervalsColSize = (int*)malloc(sizeof(int) * intervalsSize);
	if (!intervalsColSize) {
		fprintf(stderr, "Failed to malloc!\n");
		exit(EXIT_FAILURE);
	}
	for (int i = 0; i < intervalsSize; i++) {
		intervalsColSize[i] = 2;
	}

	int newInterval[] = {2, 5};
	int newIntervalSize = 2;
	int returnSize;
	int* returnColumnSizes;

	int** res = insert(intervals, intervalsSize, intervalsColSize, newInterval, newIntervalSize, &returnSize, &returnColumnSizes);

	// 打印结果
	printf("[");
	for (int i = 0; i < returnSize; i++) {
		printf("[%d, %d]", res[i][0], res[i][1]);
		if (i != returnSize - 1) {
			printf(",");
		}
	}
	printf("]");

    // 释放内存
	free(returnColumnSizes);
    free(intervalsColSize);
    // 必须先释放每一行的内存
    for (int i = 0; i < returnSize; i++) {
	    free(res[i]);
    }
    // 再释放行指针数组
    free(res);
}

测试打印结果:

ok!

相关推荐
姜行运几秒前
数据结构【栈和队列附顺序表应用算法】
android·c语言·数据结构·算法
禹曦a6 分钟前
Java进阶之旅-day05:网络编程
java·开发语言·网络
地平线开发者8 分钟前
智能驾驶中预测模块简介
算法·自动驾驶
小森77679 分钟前
(八)PMSM驱动控制学习---无感控制之滑膜观测器
算法·嵌入式·电机控制·foc·永磁同步电机·滑模控制
雾里看山12 分钟前
算法思想之双指针(二)
算法·推荐算法
地平线开发者12 分钟前
征程 6|工具链 VP 示例中日志打印解读
算法·自动驾驶
Evand J20 分钟前
【MATLAB例程】TDOA(到达时间差)定位的chan-tylor计算方法,三维环境,附代码下载链接
开发语言·matlab
飞川00120 分钟前
【LeetCode 热题100】146:LRU 缓存(详细解析)(Go语言版)
算法
uhakadotcom27 分钟前
Supervised Fine-Tuning(SFT)最佳实践
算法·面试·github
難釋懷31 分钟前
JavaScript基础-移动端常用开发框架
开发语言·javascript