LeetCode/设置交集大小至少为2(区间问题)
一个整数区间 [a, b] ( a < b ) 代表着从 a 到 b 的所有连续整数,包括 a 和 b
给你一组整数区间intervals,请找到一个最小的集合 S,使得 S 里的元素与区间intervals中的每一个整数区间都至少有2个元素相交
输出这个最小集合S的大小
1. 交集大小至少为m(贪心法)
区间题目一般先进行排序
当按左边界进行升序排序,需要从后往前遍历,贪心选择左边界值
当按右边界进行升序排序,需要从前往后遍历,贪心选择右边界值
相等时,另一个边界降序排,右边界降序隔断右边影响,左边界降序隔断左边影响
//从后往前遍历,按左边界排序,贪心选择左边界的写法
class Solution {
public:
int intersectionSizeTwo(vector<vector<int>>& intervals) {
int n = intervals.size();
int res = 0;
int m = 2;
sort(intervals.begin(), intervals.end(), [&](vector<int>& a, vector<int>& b) {
if (a[0] == b[0])
return a[1] > b[1];//相同时右边界降序排(关键步骤),保证优先选小的,要选一起选
return a[0] < b[0];//左边界升序排
});
vector<int> temp(n);//区域重叠数
for (int i = n - 1; i >= 0; i--) {//从后往前遍历区间
int left = intervals[i][0];//当前左边界值
while(temp[i]++ < m) {
res++;//贪心选择左边界作为元素插入
for (int j = i-1; j >= 0; j--) {//从后往前遍历所有区间
if (intervals[j][1] < left) //前一个数右边界小于左边界
break;//中断查找
temp[j]++;//否则刚才插入的左边界,同样满足前面区间的范围
}
left++;//选取左边界之后的数(因为要m个相交)
}
}
return res;
}
};
从前往后(按右边界排序)
class Solution {
public:
int intersectionSizeTwo(vector<vector<int>>& intervals) {
int n = intervals.size();
int res = 0;
int m = 2;
sort(intervals.begin(), intervals.end(), [&](vector<int>& a, vector<int>& b) {
if (a[1] == b[1])
return a[0] > b[0];//相同时左边界降序排(相同时要选一起选,否则下次再选)
return a[1] < b[1];//右边界升序排
});
vector<int> temp(n);//区域重叠数
for (int i = 0; i < n; i++) {//从前往后遍历区间
int right = intervals[i][1];//当前右边界值
while(temp[i]++ < m) {
res++;//贪心选择右边界作为元素插入
for (int j = i+1; j < n; j++) {//从后往前遍历所有区间
if (intervals[j][0] > right) //后一个数左边界大于右边界
break;//中断查找
temp[j]++;//否则刚才插入的右边界,同样满足后面面区间的范围
}
right--;//选取右边界之前的数(因为要m个相交)
}
}
return res;
}
};
官方写法,从后往前
class Solution {
public:
void help(vector<vector<int>>& intervals, vector<vector<int>>& temp, int pos, int num) {
for (int i = pos; i >= 0; i--) {
if (intervals[i][1] < num) {
break;
}
temp[i].push_back(num);
}
}
int intersectionSizeTwo(vector<vector<int>>& intervals) {
int n = intervals.size();
int res = 0;
int m = 2;
sort(intervals.begin(), intervals.end(), [&](vector<int>& a, vector<int>& b) {
if (a[0] == b[0])
return a[1] > b[1];
return a[0] < b[0];//左边界升序排
});
vector<vector<int>> temp(n);
for (int i = n - 1; i >= 0; i--) {
for (int j = intervals[i][0], k = temp[i].size(); k < m; j++, k++) {
res++;
help(intervals, temp, i - 1, j);
}
}
return res;
}
};
2. 针对交集为2的点贪心(空间优化)
class Solution {
public:
int intersectionSizeTwo(vector<vector<int>>& intervals) {
int n = intervals.size();
int res = 0; int a,b = -1;
sort(intervals.begin(), intervals.end(), [&](vector<int>& a, vector<int>& b) {
return a[1] == b[1]?a[0] > b[0]:a[1]<b[1]; });
for (int i = 0; i < n; i++) {//从前往后遍历区间
int left = intervals[i][0],right = intervals[i][1];
if(left>b){
res = res + 2;//新增两个点
a = right-1; b = right;//更新点值
}
else if(left>a){
res++;//新增一个点
a = b; b = right;
}
}
return res;
}
};
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现