Skip to content

Commit 026ac4e

Browse files
authored
feat: add solutions to lc problem: No.0757 (#4852)
1 parent 1265d42 commit 026ac4e

File tree

3 files changed

+126
-5
lines changed

3 files changed

+126
-5
lines changed

solution/0700-0799/0757.Set Intersection Size At Least Two/README.md

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ tags:
4545
<strong>输入:</strong>intervals = [[1,3],[1,4],[2,5],[3,5]]
4646
<strong>输出:</strong>3
4747
<strong>解释:</strong>nums = [2, 3, 4].
48-
可以证明不存在元素数量为 2 的包含集合。
48+
可以证明不存在元素数量为 2 的包含集合。
4949
</pre>
5050

5151
<p><strong class="example">示例 3:</strong></p>
@@ -54,7 +54,7 @@ tags:
5454
<strong>输入:</strong>intervals = [[1,2],[2,3],[2,4],[4,5]]
5555
<strong>输出:</strong>5
5656
<strong>解释:</strong>nums = [1, 2, 3, 4, 5].
57-
可以证明不存在元素数量为 4 的包含集合。
57+
可以证明不存在元素数量为 4 的包含集合。
5858
</pre>
5959

6060
<p>&nbsp;</p>
@@ -75,9 +75,31 @@ tags:
7575

7676
### 方法一:排序 + 贪心
7777

78-
相似题目:
78+
我们希望在数轴上选出尽可能少的整数点,使得每个区间都至少包含两个点。一个经典而有效的策略是按照区间的右端点进行排序,并尽量让已选取的点位于区间的右侧,以便这些点能覆盖更多后续区间。
79+
80+
首先将所有区间按照如下规则排序:
81+
82+
1. 按右端点从小到大;
83+
2. 若右端点相同,按左端点从大到小。
84+
85+
这样排序的原因是:右端点越小的区间“可操作空间”越少,应优先满足;当右端点相同时,左端点更大的区间更窄,更应优先被处理。
86+
87+
随后,我们使用两个变量 $s$ 和 $e$ 分别记录当前所有已处理区间所共同拥有的 **倒数第二个点****最后一个点**。初始时 $s = e = -1$,表示还没有放置任何点。
88+
89+
接下来依次处理排序后的区间 $[a, b]$,根据它与 $\{s, e\}$ 的关系分三种情况讨论:
90+
91+
1. **若 $a \leq s$**
92+
当前区间已包含 $s$ 和 $e$ 两个点,无需额外放点。
93+
94+
2. **若 $s < a \leq e$**
95+
当前区间只包含一个点(即 $e$),还需要补一个点。为了让新点对后续区间最有帮助,我们选择在区间最右侧的点 $b$。此时更新 $\textit{ans} = \textit{ans} + 1$,并将新的两点设为 $\{e, b\}$。
7996

80-
- [452. 用最少数量的箭引爆气球](https://github.com/doocs/leetcode/blob/main/solution/0400-0499/0452.Minimum%20Number%20of%20Arrows%20to%20Burst%20Balloons/README.md)
97+
3. **若 $a > e$**
98+
当前区间完全不包含已有的两个点,需要补两个点。最优选择是在区间最右侧放置 $\{b - 1, b\}$。此时更新 $\textit{ans} = \textit{ans} + 2$,并将新的两点设为 $\{b - 1, b\}$。
99+
100+
最终返回总共放置的点数 $\textit{ans}$。
101+
102+
时间复杂度 $O(n \times \log n)$,空间复杂度 $O(\log n)$。其中 $n$ 为区间的数量。
81103

82104
<!-- tabs:start -->
83105

@@ -188,6 +210,32 @@ func intersectionSizeTwo(intervals [][]int) int {
188210
}
189211
```
190212

213+
#### TypeScript
214+
215+
```ts
216+
function intersectionSizeTwo(intervals: number[][]): number {
217+
intervals.sort((a, b) => (a[1] !== b[1] ? a[1] - b[1] : b[0] - a[0]));
218+
let s = -1;
219+
let e = -1;
220+
let ans = 0;
221+
for (const [a, b] of intervals) {
222+
if (a <= s) {
223+
continue;
224+
}
225+
if (a > e) {
226+
ans += 2;
227+
s = b - 1;
228+
e = b;
229+
} else {
230+
ans += 1;
231+
s = e;
232+
e = b;
233+
}
234+
}
235+
return ans;
236+
}
237+
```
238+
191239
<!-- tabs:end -->
192240

193241
<!-- solution:end -->

solution/0700-0799/0757.Set Intersection Size At Least Two/README_EN.md

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,33 @@ It can be shown that there cannot be any containing array of size 4.
7171

7272
<!-- solution:start -->
7373

74-
### Solution 1
74+
### Solution 1: Sorting + Greedy
75+
76+
We want to select as few integer points as possible on the number line such that each interval contains at least two points. A classic and effective strategy is to sort intervals by their right endpoints and try to place selected points towards the right side of intervals, so that these points can cover more subsequent intervals.
77+
78+
First, sort all intervals by the following rules:
79+
80+
1. Sort by right endpoint in ascending order;
81+
2. If right endpoints are equal, sort by left endpoint in descending order.
82+
83+
The reason for this sorting is: intervals with smaller right endpoints have less "operational space" and should be satisfied first; when right endpoints are equal, intervals with larger left endpoints are narrower and should be prioritized.
84+
85+
Next, we use two variables $s$ and $e$ to record the **second-to-last point** and **last point** that are common to all currently processed intervals. Initially, $s = e = -1$, indicating that no points have been placed yet.
86+
87+
Then we process the sorted intervals $[a, b]$ one by one, and discuss three cases based on their relationship with $\{s, e\}$:
88+
89+
1. **If $a \leq s$**:
90+
The current interval already contains both points $s$ and $e$, so no additional points are needed.
91+
92+
2. **If $s < a \leq e$**:
93+
The current interval only contains one point (i.e., $e$), and needs one more point. To make the new point most helpful for subsequent intervals, we choose the rightmost point $b$ in the interval. Update $\textit{ans} = \textit{ans} + 1$, and set the new two points to $\{e, b\}$.
94+
95+
3. **If $a > e$**:
96+
The current interval does not contain either of the existing two points, so two points need to be added. The optimal choice is to place $\{b - 1, b\}$ at the rightmost side of the interval. Update $\textit{ans} = \textit{ans} + 2$, and set the new two points to $\{b - 1, b\}$.
97+
98+
Finally, return the total number of points placed, $\textit{ans}$.
99+
100+
The time complexity is $O(n \times \log n)$ and the space complexity is $O(\log n)$, where $n$ is the number of intervals.
75101

76102
<!-- tabs:start -->
77103

@@ -182,6 +208,32 @@ func intersectionSizeTwo(intervals [][]int) int {
182208
}
183209
```
184210

211+
#### TypeScript
212+
213+
```ts
214+
function intersectionSizeTwo(intervals: number[][]): number {
215+
intervals.sort((a, b) => (a[1] !== b[1] ? a[1] - b[1] : b[0] - a[0]));
216+
let s = -1;
217+
let e = -1;
218+
let ans = 0;
219+
for (const [a, b] of intervals) {
220+
if (a <= s) {
221+
continue;
222+
}
223+
if (a > e) {
224+
ans += 2;
225+
s = b - 1;
226+
e = b;
227+
} else {
228+
ans += 1;
229+
s = e;
230+
e = b;
231+
}
232+
}
233+
return ans;
234+
}
235+
```
236+
185237
<!-- tabs:end -->
186238

187239
<!-- solution:end -->
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
function intersectionSizeTwo(intervals: number[][]): number {
2+
intervals.sort((a, b) => (a[1] !== b[1] ? a[1] - b[1] : b[0] - a[0]));
3+
let s = -1;
4+
let e = -1;
5+
let ans = 0;
6+
for (const [a, b] of intervals) {
7+
if (a <= s) {
8+
continue;
9+
}
10+
if (a > e) {
11+
ans += 2;
12+
s = b - 1;
13+
e = b;
14+
} else {
15+
ans += 1;
16+
s = e;
17+
e = b;
18+
}
19+
}
20+
return ans;
21+
}

0 commit comments

Comments
 (0)