题目链接:
题目简介:
描述
给出一组区间,请合并所有重叠的区间。
请保证合并后的区间按区间起点升序排列。
数据范围:区间组数 0≤n≤2×10^5,区间内 的值都满足 0≤val≤2×10^5
要求:空间复杂度 O(n),时间复杂度 O(nlogn)
进阶:空间复杂度 O(val),时间复杂度O(val)
题目解法:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
/*
*BM89 合并区间
描述
给出一组区间,请合并所有重叠的区间。
请保证合并后的区间按区间起点升序排列。
数据范围:区间组数 0≤n≤2×10^5 ,区间内 的值都满足 0≤val≤2×10^5
要求:空间复杂度 O(n),时间复杂度 O(nlogn)
进阶:空间复杂度 O(val),时间复杂度O(val)
*/
struct Interval {
int start;
int end;
};
struct Interval* merge(struct Interval* intervals, int intervalsLen, int* returnSize ) {
// write code here
int tmpStart, tmpEnd; //当前开头,当前结尾
int tmpMinStart, tmpMinEnd, tmp; //未使用的当前最小起始区间的开头结尾
struct Interval *retInterval = (struct Interval*)malloc(sizeof(struct Interval)*intervalsLen);
// int useFlag[5] = {1,1,1,1,1}; //本地测试代码
int *useFlag = (int*)malloc(sizeof(int)*intervalsLen); //未使用为1,已使用为0
for(int i=0; i<intervalsLen; i++){
*(useFlag+i) = 1;
}
*returnSize = 0; //初始化返回结构体的长度
for(int i=0; i < intervalsLen; i++){
if(useFlag[i] == 0) //如果当前区间已使用,则跳过
continue;
tmpStart = intervals[i].start, tmpEnd = intervals[i].end; //获得当前区间的起始和结尾
tmpMinStart = -1, tmpMinEnd = -1; //清空,初始化表示没找到最小起始区间
useFlag[i] = 0; //标志当前区间已使用
for(int j=i+1; j <= intervalsLen; j++){ //从当前区间下一个开始,循环
if(j == intervalsLen){ //判断是否到最后一个区间
if(tmpMinStart <= tmpEnd && tmpMinEnd >= tmpStart){ //intervals中还有未合并区间,则继续从当前区间的下一个进行循环
tmpMinStart = -1, tmpMinEnd = -1;
j = i; //重新开始循环,相当于j=i+1
continue;
}
break;
}
if(useFlag[j] == 0) //如果当前区间已使用,则跳过
continue;
if(tmpStart <= intervals[j].end && tmpEnd >= intervals[j].start){ //当前区间与比较区间有重合
useFlag[j] = 0; //标志比较区间已使用
tmpStart = tmpStart < intervals[j].start ? tmpStart : intervals[j].start ;//更新合并后区间的起始、结尾
tmpEnd = tmpEnd > intervals[j].end ? tmpEnd : intervals[j].end;
}else{ //当前区间与比较区间没重合
if(tmpMinStart == -1 || tmpMinStart > intervals[j].start){ //判断:1、未初始化,则赋初值 2、找到更小的起始区间
tmpMinStart = intervals[j].start; //将未使用的区间且起始区间更小的比较区间记录
tmpMinEnd = intervals[j].end;
}
}
}
retInterval[*returnSize].start = tmpStart; //将合并后的区间开头赋值
retInterval[*returnSize].end = tmpEnd; //将合并后的区间结尾赋值
(*returnSize)++; //返回区间数量+1
}
for(int i=0; i<*returnSize; i++){ //冒泡排序
for(int j=i; j<*returnSize; j++){
if(retInterval[i].start > retInterval[j].start){
tmp = retInterval[i].start;
retInterval[i].start = retInterval[j].start;
retInterval[j].start = tmp;
tmp = retInterval[i].end;
retInterval[i].end = retInterval[j].end;
retInterval[j].end = tmp;
}
}
}
return retInterval;
}
/**************************end******************************************/
int main ()
{
int retSize = 0;
// struct Interval t1 = {10,30};
// struct Interval t2 = {20,60};
// struct Interval t3 = {80,100};
// struct Interval t4 = {150,180};
// struct Interval t1 = {10,30};
// struct Interval t2 = {40,80};
// struct Interval t3 = {80,100};
// struct Interval t4 = {30,180};
// struct Interval t1 = {1,4};
// struct Interval t2 = {0,0};
// struct Interval t1 = {0,2};
// struct Interval t2 = {2,3};
// struct Interval t3 = {4,4};
// struct Interval t4 = {0,1};
// struct Interval t5 = {5,7};
// struct Interval t6 = {4,5};
// struct Interval t7 = {0,0};
struct Interval t1 = {2,3};
struct Interval t2 = {4,5};
struct Interval t3 = {6,7};
struct Interval t4 = {8,9};
struct Interval t5 = {1,10};
struct Interval pt[] = {t1,t2,t3,t4,t5};
struct Interval* ret = merge(pt, 5, &retSize);
for(int i=0; i<retSize; i++){
printf("\r\n [%d, %d]", (ret+i)->start, (ret+i)->end);
}
return 0;
}