给你一个二维整数数组 intervals ,其中 intervals[i] = [lefti, righti] 表示 闭   区间[lefti, righti] 。
你需要将 intervals 划分为一个或者多个区间  组   ,每个区间 只   属于一个组,且同一个组中任意两个区间 不相交 
请你返回 最少   需要划分成多少个组。
如果两个区间覆盖的范围有重叠(即至少有一个公共数字),那么我们称这两个区间是 相交   的。比方说区间 [1, 5] 和 [5, 8] 相交。
示例 1: 
**输入:** intervals = [[5,10],[6,8],[1,5],[2,3],[1,10]]
**输出:** 3
**解释:** 我们可以将区间划分为如下的区间组:
- 第 1 组:[1, 5] ,[6, 8] 。
- 第 2 组:[2, 3] ,[5, 10] 。
- 第 3 组:[1, 10] 。
可以证明无法将区间划分为少于 3 个组。
示例 2: 
**输入:** intervals = [[1,3],[5,6],[8,10],[11,13]]
**输出:** 1
**解释:** 所有区间互不相交,所以我们可以把它们全部放在一个组内。
提示: 
1 <= intervals.length <= 105intervals[i].length == 21 <= lefti <= righti <= 106 
本题 视频讲解   已出炉,欢迎点赞三连,在评论区分享你对这场周赛的看法~
按照 left 排序后,用最小堆模拟,堆顶存储每个组最后一个区间的 right。
遍历区间:
如果当前的 left 大于堆顶,则可以接在这个组的末尾,更新堆顶为 right; 
否则需要创建一个新的组。 
 
[sol1-Python3] 1 2 3 4 5 6 7 8 class  Solution :    def  minGroups (self, intervals: List [List [int ]] ) -> int :         intervals.sort(key=lambda  p: p[0 ])         h = []         for  left, right in  intervals:             if  h and  left > h[0 ]: heapreplace(h, right)             else : heappush(h, right)         return  len (h) 
[sol1-Java] 1 2 3 4 5 6 7 8 9 10 11 class  Solution  {    public  int  minGroups (int [][] intervals)  {         Arrays.sort(intervals, (a, b) -> a[0 ] - b[0 ]);         var  pq  =  new  PriorityQueue <Integer>();         for  (var  p : intervals) {             if  (!pq.isEmpty() && pq.peek() < p[0 ]) pq.poll();             pq.offer(p[1 ]);         }         return  pq.size();     } } 
[sol1-C++] 1 2 3 4 5 6 7 8 9 10 11 12 class  Solution  {public :    int  minGroups (vector<vector<int >> &intervals)           sort (intervals.begin (), intervals.end (), [](auto  &a, auto  &b) { return  a[0 ] < b[0 ]; });         priority_queue<int , vector<int >, greater<>> pq;         for  (auto  &p : intervals) {             if  (!pq.empty () && pq.top () < p[0 ]) pq.pop ();             pq.push (p[1 ]);         }         return  pq.size ();     } }; 
[sol1-Go] 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 func  minGroups (intervals [][]int ) int  {	h := hp{} 	sort.Slice(intervals, func (i, j int ) bool  { return  intervals[i][0 ] < intervals[j][0 ] }) 	for  _, p := range  intervals { 		if  h.Len() == 0  || p[0 ] <= h.IntSlice[0 ] { 			heap.Push(&h, p[1 ]) 		} else  { 			h.IntSlice[0 ] = p[1 ] 			heap.Fix(&h, 0 ) 		} 	} 	return  h.Len() } type  hp struct { sort.IntSlice }func  (h *hp) interface {}) { h.IntSlice = append (h.IntSlice, v.(int )) }func  (h *hp) interface {}   { a := h.IntSlice; v := a[len (a)-1 ]; h.IntSlice = a[:len (a)-1 ]; return  v }
另外一种思路是转换成上下车模型,每个区间看成一个人,他在 left 时刻上车,right}+1 时刻下车,最后答案为同时在车上的人数的最大值。
这可以用差分数组实现,下面代码用的平衡树,方便从小到大计算。
[sol2-C++] 1 2 3 4 5 6 7 8 9 10 11 12 class  Solution  {public :    int  minGroups (vector<vector<int >> &intervals)           map<int , int > diff;         for  (auto  &p : intervals)             ++diff[p[0 ]], --diff[p[1 ] + 1 ];         int  ans = 0 , sum = 0 ;         for  (auto  &[_, d] : diff)             ans = max (ans, sum += d);         return  ans;     } }; 
复杂度分析 
时间复杂度:O(n\log n),其中 n 为 nums 的长度。 
空间复杂度:O(n)。 
 
思考题 从所有满足 1\le\textit{left}\le\textit{right}\le m 的一共 \dfrac{m(m+1)}{2 个区间中,随机选择 n 个区间作为本题的输入,得到的答案的期望是多少?