普通视图

发现新文章,点击刷新页面。
今天 — 2025年11月20日首页

设置交集大小至少为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做为开始的两个集合元素,设初始两个元素为curnext,则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
    image.png
    最后返回答案即可
    代码如下
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++代码
image.png
给大家写了一个打印结果的代码,方便大家理解
代码如下

    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]

写题解不易,如果对您有帮助,记得关注 + 点赞 + 收藏呦!!!
每天都会更新每日一题题解,大家加油!!

❌
❌