leetcode757. 设置交集大小至少为2 - 实践

757. 设置交集大小至少为2

给你一个二维整数数组 intervals ,其中 intervals[i] = [starti, endi] 表示从 startiendi 的所有整数,包括 startiendi

包含集合 是一个名为 nums 的数组,并满足 intervals 中的每个区间都 至少 有 两个 整数在 nums 中。

例如,如果 intervals = [[1,3], [3,7], [8,9]] ,那么 [1,2,4,7,8,9][2,3,4,8,9] 都符合 包含集合 的定义。
返回包含集合可能的最小大小。

示例 1:

输入:intervals = [[1,3],[3,7],[8,9]]
输出:5
解释:nums = [2, 3, 4, 8, 9].
可以证明不存在元素数量为 4 的包含集合。

示例 2:

输入:intervals = [[1,3],[1,4],[2,5],[3,5]]
输出:3
解释:nums = [2, 3, 4].
可以证明不存在元素数量为 2 的包含集合。

示例 3:

输入:intervals = [[1,2],[2,3],[2,4],[4,5]]
输出:5
解释:nums = [1, 2, 3, 4, 5].
可以证明不存在元素数量为 4 的包含集合。

提示:

1 <= intervals.length <= 3000
intervals[i].length == 2
0 <= starti < endi <= 108

方法一:贪心

思路与算法

首先我们从稍简化的情况开始分析:如果题目条件为设置交集大小为1,为了更好的分析我们将intervals按照[s,e]序对进行升序排序,其中intervals为题目给出的区间集合,s,e为区间的左右边界。设排序后的intervals={[s1,e1],...,[sn,en]},其中n为区间集合的大小,并满足 ∀ i , j ∈ [ 1 , n ] , i < j \forall i,j\in[1,n],i<j i,j[1,n],i<j s i ≤ s j s_{i}\leq s_{j} sisj 成立。然后对于最后一个区间 [ s n , e n ] [s_{n},e_{n}] [sn,en] 来说一定要提供一个最后交集集合中的元素,那么我们思考我们选择该区间中哪个元素是最优的——最优的元素应该尽可能的把之前的区间尽可能的覆盖。那么我们选择该区间的开头元素 s n s_{n} sn 一定是最优的,因为对于前面的某一个区间 [ s i , e i ] [s_{i},e_{i}] [si,ei]

  • 如果 e i < s n e_{i}<s_{n} ei<sn:那么无论选择最后一个区间中的哪个数字都不会在区间 [ s i , e i ] [s_{i},e_{i}] [si,ei] 中。
  • 否则 e i ≥ s n e_{i}\geq s_{n} eisn:因为 s n ≥ s i s_{n}\geq s_{i} snsi 所以此时选择 s n s_{n} sn 一定会在区间 [ s i , e i ] [s_{i},e_{i}] [si,ei] 中。

即对于最后一个区间 [ s n , e n ] [s_{n},e_{n}] [sn,en] 来说选择区间的开头元素 s n s_{n} sn 一定是最优的。那么贪心的思路就出来了:排序后从后往前进行遍历,每次选取与当前交集集合相交为空的区间的最左边的元素即可,然后往前判断前面是否有区间能因此产生交集,产生交集的直接跳过即可。此时算法的时间复杂度为: O ( n log ⁡ n ) O(n\log n) O(nlogn) 主要为排序的时间复杂度。对于这种情况具体也可以见leetcode题目452. 用最少数量的箭引爆气球

那么我们用同样的思路来扩展到需要交集为mm>1的情况:此时同样首先对intervals按照[s,e]序对进行升序排序,然后我们需要额外记录每一个区间与最后交集集合中相交的元素(只记录到m个为止)。同样我们从最后一个区间往前进行处理,如果该区间与交集集合相交元素个数小于m个时,我们从该区间左边界开始往后添加不在交集集合中的元素,并往前进行更新需要更新的区间,重复该过程直至该区间与交集元素集合有m个元素相交。到此就可以解决问题了,不过我们也可以来修改排序的规则——我们将区间[s,e]序对按照s升序,当s相同时按照e降序来进行排序,这样可以实现在处理与交集集合相交元素个数小于m个的区间 [ s i , e i ] [s_{i},e_{i}] [si,ei] 时,保证不足的元素都是在区间的开始部分,即我们可以直接从区间开始部分进行往交集集合中添加元素。

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;
        }
        };
posted @ 2026-02-08 10:52  clnchanpin  阅读(9)  评论(0)    收藏  举报