一个整数区间 [a, b]
( a < b
) 代表着从 a
到 b
的所有连续整数,包括 a
和 b
。
给你一组整数区间intervals
,请找到一个最小的集合 S,使得 S 里的元素与区间intervals
中的每一个整数区间都至少有2个元素相交。
输出这个最小集合S的大小。
示例 1:
输入: intervals = [[1, 3], [1, 4], [2, 5], [3, 5]] 输出: 3 解释: 考虑集合 S = {2, 3, 4}. S与intervals中的四个区间都有至少2个相交的元素。 且这是S最小的情况,故我们输出3。
示例 2:
输入: intervals = [[1, 2], [2, 3], [2, 4], [4, 5]] 输出: 5 解释: 最小的集合S = {1, 2, 3, 4, 5}.
注意:
intervals
的长度范围为[1, 3000]
。intervals[i]
长度为2
,分别代表左、右边界。intervals[i][j]
的值是[0, 10^8]
范围内的整数。
方法一:排序 + 贪心
相似题目: 452. 用最少数量的箭引爆气球
class Solution:
def intersectionSizeTwo(self, intervals: List[List[int]]) -> int:
intervals.sort(key=lambda x: (x[1], -x[0]))
s = e = -1
ans = 0
for a, b in intervals:
if a <= s:
continue
if a > e:
ans += 2
s, e = b - 1, b
else:
ans += 1
s, e = e, b
return ans
class Solution {
public int intersectionSizeTwo(int[][] intervals) {
Arrays.sort(intervals, (a, b) -> a[1] == b[1] ? b[0] - a[0] : a[1] - b[1]);
int ans = 0;
int s = -1, e = -1;
for (int[] v : intervals) {
int a = v[0], b = v[1];
if (a <= s) {
continue;
}
if (a > e) {
ans += 2;
s = b - 1;
e = b;
} else {
ans += 1;
s = e;
e = b;
}
}
return ans;
}
}
class Solution {
public:
int intersectionSizeTwo(vector<vector<int>>& intervals) {
sort(intervals.begin(), intervals.end(), [&](vector<int>& a, vector<int>& b) {
return a[1] == b[1] ? a[0] > b[0] : a[1] < b[1];
});
int ans = 0;
int s = -1, e = -1;
for (auto& v : intervals) {
int a = v[0], b = v[1];
if (a <= s) continue;
if (a > e) {
ans += 2;
s = b - 1;
e = b;
} else {
ans += 1;
s = e;
e = b;
}
}
return ans;
}
};
func intersectionSizeTwo(intervals [][]int) int {
sort.Slice(intervals, func(i, j int) bool {
a, b := intervals[i], intervals[j]
if a[1] == b[1] {
return a[0] > b[0]
}
return a[1] < b[1]
})
ans := 0
s, e := -1, -1
for _, v := range intervals {
a, b := v[0], v[1]
if a <= s {
continue
}
if a > e {
ans += 2
s, e = b - 1, b
} else {
ans += 1
s, e = e, b
}
}
return ans
}