70.打点计数器的区间合并
问题描述
小明正在设计一台打点计数器,该计数器可以接受多个递增的数字范围,并对这些范围内的每个唯一数字打点。如果多个范围之间有重叠,计数器将合并这些范围并只对每个唯一数字打一次点。小明需要你帮助他计算,在给定的多组数字范围内,计数器会打多少个点。
例如,给定三个数字范围 [1, 4], [7, 10], 和 [3, 5],计数器首先将这些范围合并,变成 [1, 5] 和 [7, 10],然后计算这两个范围内共有多少个唯一数字,即从 1 到 5 有 5 个数字,从 7 到 10 有 4 个数字,共打 9 个点。
1.思路
1.以区间左端点为关键字做快排
2.判断区间关系
若i区间左端点小于等于已存结尾,则i区间与前面区间相交,合并i区间 若i区间左端点大于已存结尾,则i区间与前面区间不相交,将前面区间提取到res数组中,并将起点重设为i区间左端点
3.计算打点数
遍历合并后的区间数组,计算每个区间的长度:`length = ed - st + 1`,累加得到总数字数
2.注意事项
1.初始化
初始化区间起点st和终点ed为一个极小值(例如-2e9),表示当前没有处理区间。
如果输入为空,则直接返回结果为0。
2.边界情况
如果只有一个区间,直接返回该区间的数字数量。 如果所有区间互不重叠,结果就是各区间长度的总和。
3.复杂度
1.时间复杂度
将输入的区间按左端点排序,复杂度为 O(nlogn),其中 n 是区间的数量,并且这是最大时间复杂度,因此,时间复杂度为O(nlogn)
2.空间复杂度
存储输入区间和合并后的结果区间,需要额外的 O(n) 空间。 排序操作可能使用额外的栈空间(递归深度),最坏情况为 O(logn)
综合空间复杂度为:O(n)
4.代码实现
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> PII;
int solution(std::vector<std::vector<int>> inputArray) {
// Please write your code here
int st=-2e9,ed=-2e9;
vector<PII> segs;
vector<PII> res;
int cnt=0;
for(int i=0;i<inputArray.size();i++){
segs.push_back({inputArray[i][0],inputArray[i][1]});
}
sort(segs.begin(),segs.end());
for(auto item:segs){
if(ed<item.first){
if(st!=-2e9) res.push_back({st,ed});
st=item.first;
ed=item.second;
}else{
ed=max(ed,item.second);
}
}
if(st!=-2e9) res.push_back({st,ed});
for(int i=0;i<res.size();i++){
cnt+=(res[i].second-res[i].first+1);
}
return cnt;
}
int main() {
// You can add more test cases here
std::vector<std::vector<int>> testArray1 = {{1, 4}, {7, 10}, {3, 5}};
std::vector<std::vector<int>> testArray2 = {{1, 2}, {6, 10}, {11, 15}};
std::cout << (solution(testArray1) == 9) << std::endl;
std::cout << (solution(testArray2) == 12) << std::endl;
return 0;
}