设置交集大小至少为2【贪心】
2022年7月22日 08:07
方法一:贪心
我们对intervals进行排序,intervals[0]升序,inervals[1]降序,然后从后向前进行遍历。
为什么要一个升序一个降序呢?
假设我们有一个intervals = [[2,3],[3,4],[5,10],[5,8]] (已排好序), 只要我们满足了和[5,8]的交集大于等于2,则对于[5,10](左区间相同,右区间降序,保证在左区间相同的情况下让区间范围最小的在最右边)这个区间来说,必定是满足交集大于等于2的,因为小区间满足,大区间必然满足,反过来不一定,在左区间相同的情况下,我们取最小区间的两个元素就可以满足所有左区间相同的区间。因此我们贪心的取interval[n-1][0]和interval[n-1][0] + 1做为开始的两个集合元素,设初始两个元素为cur和next,则cur = intervals[n - 1][0],next = intervals[n - 1][0] + 1。
然后开始分类讨论上一个区间[xi,yi]的情况,根据排序有xi <= cur
- 若
yi >= next,则是一个大区间,一定满足交集为2的情况 - 若
yi < cur,那一定没有交集,我们还是贪心的取cur = xi,next = xi + 1 - 若
cur <= yi < next,有一个交集,我们贪心的取next = cur,cur = xi
保证每次都是取左边界或者左边界和左边界+1
最后返回答案即可
代码如下
class Solution {
public int intersectionSizeTwo(int[][] intervals) {
Arrays.sort(intervals, (o1, o2) -> o1[0] == o2[0] ? o2[1] - o1[1] : o1[0] - o2[0]);
int n = intervals.length;
//初始的两个元素
int cur = intervals[n - 1][0];
int next = intervals[n - 1][0] + 1;
int ans = 2;
//从后向前遍历
for (int i = n - 2; i >= 0; i--) {
//开始分类讨论
if (intervals[i][1] >= next) {
continue;
} else if (intervals[i][1] < cur) {
cur = intervals[i][0];
next = intervals[i][0] + 1;
ans = ans + 2;
} else {
next = cur;
cur = intervals[i][0];
ans++;
}
}
return ans;
}
}
class Solution:
def intersectionSizeTwo(self, intervals: List[List[int]]) -> int:
if not intervals:
return 0
intervals.sort(key = lambda x : (x[0], -x[1]))
ans = 2
cur, next = intervals[-1][0], intervals[-1][0]+1
for xi, yi in reversed(intervals[:-1]):
if yi >= next:
continue
elif yi < cur:
cur = xi
next = xi + 1
ans += 2
elif cur <= yi < next:
next = cur
cur = xi
ans += 1
return ans
class Solution {
public:
int intersectionSizeTwo(vector<vector<int>>& intervals) {
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];
}); // 左边界升序,若相同,右边界降序
int res = 2, ls = intervals.back()[0], rs = ls + 1;
for(int i = intervals.size() - 2; i >= 0; i--){
if(intervals[i][1] >= rs){ // 有两个及以上的交点
continue;
}else if(intervals[i][1] < ls){ // 没有交点
ls = intervals[i][0];
rs = intervals[i][0] + 1;
res += 2;
}else{ // 一个交点
rs = ls;
ls = intervals[i][0];
res++;
}
}
return res;
}
};
感谢@fergus-peng小伙伴的py代码
感谢@handsomechar小伙伴的c++代码![]()
给大家写了一个打印结果的代码,方便大家理解
代码如下
public int intersectionSizeTwo(int[][] intervals) {
Arrays.sort(intervals, (o1, o2) -> o1[0] == o2[0] ? o2[1] - o1[1] : o1[0] - o2[0]);
System.out.println("排序后intervals:" + Arrays.deepToString(intervals));
int n = intervals.length;
int cur = intervals[n - 1][0];
int next = intervals[n - 1][0] + 1;
int ans = 2;
List<Integer> list = new ArrayList<>();
list.add(cur);
list.add(next);
for (int i = n - 2; i >= 0; i--) {
System.out.println("待比较区间:" + Arrays.toString(intervals[i]) + "\t当前集合S:" + list);
if (intervals[i][1] >= next) {
continue;
} else if (intervals[i][1] < cur) {
cur = intervals[i][0];
next = intervals[i][0] + 1;
ans = ans + 2;
list.add(0, next);
list.add(0, cur);
} else {
next = cur;
cur = intervals[i][0];
ans++;
list.add(0, cur);
}
}
return ans;
}
示例:
int[][] intervals = {{2, 10}, {3, 7}, {3, 15}, {4, 11}, {6, 12}, {6, 16}, {7, 8}, {7, 11}, {7, 15}, {11, 12}};
//结果
排序后intervals:[[2, 10], [3, 15], [3, 7], [4, 11], [6, 16], [6, 12], [7, 15], [7, 11], [7, 8], [11, 12]]
待比较区间:[7, 8]当前集合S:[11, 12]
待比较区间:[7, 11]当前集合S:[7, 8, 11, 12]
待比较区间:[7, 15]当前集合S:[7, 8, 11, 12]
待比较区间:[6, 12]当前集合S:[7, 8, 11, 12]
待比较区间:[6, 16]当前集合S:[7, 8, 11, 12]
待比较区间:[4, 11]当前集合S:[7, 8, 11, 12]
待比较区间:[3, 7]当前集合S:[7, 8, 11, 12]
待比较区间:[3, 15]当前集合S:[3, 7, 8, 11, 12]
待比较区间:[2, 10]当前集合S:[3, 7, 8, 11, 12]
写题解不易,如果对您有帮助,记得关注 + 点赞 + 收藏呦!!!
每天都会更新每日一题题解,大家加油!!