Skip to content

Commit 37a4490

Browse files
authored
Merge pull request #637 from LetMeFly666/632
添加问题“632.最小区间”的代码和题解
2 parents edf1c62 + 1b26509 commit 37a4490

7 files changed

+288
-356
lines changed
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
/*
2+
* @Author: LetMeFly
3+
* @Date: 2024-11-24 17:37:00
4+
* @LastEditors: LetMeFly.xyz
5+
* @LastEditTime: 2024-11-24 18:31:53
6+
*/
7+
#ifdef _WIN32
8+
#include "_[1,2]toVector.h"
9+
#endif
10+
11+
#ifdef FirstTry // TLE(92 / 94 个通过的测试用例) // 最后可能全部移动的最后一组的指针,但是前面的元素还要全部再判断并continue一次
12+
/*
13+
4 10 15
14+
0 9 12
15+
16+
0-4
17+
4-9
18+
9-10
19+
10-12
20+
12-15
21+
22+
min: 9-10
23+
*/
24+
class Solution {
25+
private:
26+
void update(vector<vector<int>>& nums, vector<int>& loc, int& m, int& M) {
27+
m = 1e6, M = -1e6;
28+
for (int i = 0; i < nums.size(); i++) {
29+
m = min(m, nums[i][loc[i]]);
30+
M = max(M, nums[i][loc[i]]);
31+
}
32+
}
33+
public:
34+
vector<int> smallestRange(vector<vector<int>>& nums) {
35+
// init
36+
vector<int> loc(nums.size());
37+
int m, M;
38+
update(nums, loc, m, M);
39+
int minDiff = M - m;
40+
// begin
41+
while (true) {
42+
int moveWhich = -1, minChange = 1e6;
43+
for (int i = 0; i < nums.size(); i++) {
44+
if (loc[i] == nums[i].size() - 1) {
45+
continue;
46+
}
47+
if (nums[i][loc[i] + 1] - M < minChange) {
48+
moveWhich = i;
49+
minChange = nums[i][loc[i] + 1] - M;
50+
}
51+
}
52+
if (moveWhich == -1) {
53+
break;
54+
}
55+
loc[moveWhich]++;
56+
int thism, thisM;
57+
update(nums, loc, thism, thisM);
58+
if (thisM - thism < minDiff) {
59+
minDiff = thisM - thism;
60+
m = thism, M = thisM;
61+
}
62+
}
63+
return {m, M};
64+
}
65+
};
66+
#else // FirstTry
67+
#ifdef SecondTry // TLE // 时间瓶颈卡在获取m和M上
68+
class Solution {
69+
private:
70+
void updateMm(vector<vector<int>>& nums, vector<int>& loc, int& m, int& M) {
71+
m = 1e6, M = -1e6;
72+
for (int i = 0; i < nums.size(); i++) {
73+
m = min(m, nums[i][loc[i]]);
74+
M = max(M, nums[i][loc[i]]);
75+
}
76+
}
77+
public:
78+
vector<int> smallestRange(vector<vector<int>>& nums) {
79+
vector<int> loc(nums.size());
80+
int m, M;
81+
updateMm(nums, loc, m, M);
82+
int minDiff = M - m;
83+
priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
84+
for (int i = 0; i < nums.size(); i++) {
85+
for (int j = 1; j < nums[i].size(); j++) {
86+
pq.push({nums[i][j], i});
87+
}
88+
}
89+
while (pq.size()) {
90+
auto&& [val, index] = pq.top();
91+
loc[index]++;
92+
pq.pop();
93+
int thism, thisM;
94+
updateMm(nums, loc, thism, thisM);
95+
if (thisM - thism < minDiff) {
96+
minDiff = thisM - thism;
97+
m = thism, M = thisM;
98+
}
99+
}
100+
return {m, M};
101+
}
102+
};
103+
#else // SecondTry
104+
#ifdef ThirdTry // WA - 最终会收敛到[最大数, 最大数]
105+
class Solution {
106+
public:
107+
vector<int> smallestRange(vector<vector<int>>& nums) {
108+
vector<int> loc(nums.size());
109+
// lambda [](const int& x, const int& y)->bool cmp = xxx
110+
auto cmp = [&nums, &loc](const int& x, const int& y) {
111+
return nums[x][loc[x]] > nums[y][loc[y]];
112+
};
113+
priority_queue<int, vector<int>, decltype(cmp)> pq(cmp);
114+
int m = -1e8, M = -1e6;
115+
for (int i = 0; i < nums.size(); i++) {
116+
pq.push(i);
117+
M = max(M, nums[i][0]);
118+
}
119+
int nowm, nowM = M;
120+
while (pq.size()) {
121+
int index = pq.top();
122+
pq.pop();
123+
nowm = nums[index][loc[index]];
124+
loc[index]++;
125+
if (nowM - nowm < M - m) {
126+
M = nowM;
127+
m = nowm;
128+
}
129+
if (loc[index] < nums[index].size()) {
130+
nowM = max(nowM, nums[index][loc[index]]);
131+
pq.push(index);
132+
}
133+
// printf("m = %d, M = %d, nowm = %d, nowM = %d\n", m, M, nowm, nowM); //*************
134+
}
135+
return {m, M};
136+
}
137+
};
138+
#else // ThirdTry
139+
// FourthTry
140+
class Solution {
141+
public:
142+
vector<int> smallestRange(vector<vector<int>>& nums) {
143+
vector<int> loc(nums.size());
144+
auto cmp = [&nums, &loc](const int& x, const int& y) {
145+
return nums[x][loc[x]] > nums[y][loc[y]];
146+
};
147+
priority_queue<int, vector<int>, decltype(cmp)> pq(cmp);
148+
int m = -1e8, M = -1e6;
149+
for (int i = 0; i < nums.size(); i++) {
150+
pq.push(i);
151+
M = max(M, nums[i][0]);
152+
}
153+
int nowm, nowM = M;
154+
while (pq.size()) {
155+
int index = pq.top();
156+
pq.pop();
157+
nowm = nums[index][loc[index]];
158+
loc[index]++;
159+
if (nowM - nowm < M - m) {
160+
M = nowM;
161+
m = nowm;
162+
}
163+
if (loc[index] == nums[index].size()) {
164+
break;
165+
}
166+
nowM = max(nowM, nums[index][loc[index]]);
167+
pq.push(index);
168+
}
169+
return {m, M};
170+
}
171+
};
172+
#endif // ThirdTry
173+
#endif // SecondTry
174+
#endif // FirstTry

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,7 @@
227227
|0617.合并二叉树|简单|<a href="https://leetcode.cn/problems/merge-two-binary-trees/solutions/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2023/08/14/LeetCode%200617.%E5%90%88%E5%B9%B6%E4%BA%8C%E5%8F%89%E6%A0%91/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/132268393" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/merge-two-binary-trees/solutions/2387253/letmefly-617he-bing-er-cha-shu-by-tisfy-3f89/" target="_blank">LeetCode题解</a>|
228228
|0623.在二叉树中增加一行|中等|<a href="https://leetcode.cn/problems/add-one-row-to-tree/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2022/08/05/LeetCode%200623.%E5%9C%A8%E4%BA%8C%E5%8F%89%E6%A0%91%E4%B8%AD%E5%A2%9E%E5%8A%A0%E4%B8%80%E8%A1%8C/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/126179967" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/add-one-row-to-tree/solution/letmefly-623zai-er-cha-shu-zhong-zeng-ji-ajg0/" target="_blank">LeetCode题解</a>|
229229
|0630.课程表III|困难|<a href="https://leetcode.cn/problems/course-schedule-iii/solutions/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2023/09/11/LeetCode%200630.%E8%AF%BE%E7%A8%8B%E8%A1%A8III/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/132806660" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/course-schedule-iii/solutions/2437116/letmefly-630ke-cheng-biao-iiitan-xin-you-ah0l/" target="_blank">LeetCode题解</a>|
230+
|0632.最小区间|困难|<a href="https://leetcode.cn/problems/smallest-range-covering-elements-from-k-lists/solutions/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2024/11/24/LeetCode%200632.%E6%9C%80%E5%B0%8F%E5%8C%BA%E9%97%B4/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/144011635" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/smallest-range-covering-elements-from-k-lists/solutions/2999312/letmefly-632zui-xiao-qu-jian-you-xian-du-bct2/" target="_blank">LeetCode题解</a>|
230231
|0633.平方数之和|中等|<a href="https://leetcode.cn/problems/sum-of-square-numbers/solutions/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2024/11/04/LeetCode%200633.%E5%B9%B3%E6%96%B9%E6%95%B0%E4%B9%8B%E5%92%8C/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/143495591" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/sum-of-square-numbers/solutions/2977304/letmefly-633ping-fang-shu-zhi-he-mo-ni-b-2und/" target="_blank">LeetCode题解</a>|
231232
|0638.大礼包|中等|<a href="https://leetcode.cn/problems/shopping-offers/solutions/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2024/11/03/LeetCode%200638.%E5%A4%A7%E7%A4%BC%E5%8C%85/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/143465993" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/shopping-offers/solutions/2975699/letmefly-638da-li-bao-ji-yi-hua-sou-suo-qyhoh/" target="_blank">LeetCode题解</a>|
232233
|0640.求解方程|中等|<a href="https://leetcode.cn/problems/solve-the-equation/" target="_blank">题目地址</a>|<a href="https://blog.letmefly.xyz/2022/08/10/LeetCode%200640.%E6%B1%82%E8%A7%A3%E6%96%B9%E7%A8%8B/" target="_blank">题解地址</a>|<a href="https://letmefly.blog.csdn.net/article/details/126262898" target="_blank">CSDN题解</a>|<a href="https://leetcode.cn/problems/solve-the-equation/solution/letmefly-640qiu-jie-fang-cheng-guo-ji-ti-xbzp/" target="_blank">LeetCode题解</a>|
Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
---
2+
title: 632.最小区间
3+
date: 2024-11-24 18:36:13
4+
tags: [题解, LeetCode, 困难, 贪心, 数组, 哈希表, 排序, 滑动窗口, 堆(优先队列)]
5+
---
6+
7+
# 【LetMeFly】632.最小区间:优先队列
8+
9+
力扣题目链接:[https://leetcode.cn/problems/smallest-range-covering-elements-from-k-lists/](https://leetcode.cn/problems/smallest-range-covering-elements-from-k-lists/)
10+
11+
<p>你有&nbsp;<code>k</code>&nbsp;个 <strong>非递减排列</strong> 的整数列表。找到一个 <strong>最小 </strong>区间,使得&nbsp;<code>k</code>&nbsp;个列表中的每个列表至少有一个数包含在其中。</p>
12+
13+
<p>我们定义如果&nbsp;<code>b-a &lt; d-c</code>&nbsp;或者在&nbsp;<code>b-a == d-c</code>&nbsp;&nbsp;<code>a &lt; c</code>,则区间 <code>[a,b]</code> 比 <code>[c,d]</code> 小。</p>
14+
15+
<p>&nbsp;</p>
16+
17+
<p><strong>示例 1:</strong></p>
18+
19+
<pre>
20+
<strong>输入:</strong>nums = [[4,10,15,24,26], [0,9,12,20], [5,18,22,30]]
21+
<strong>输出:</strong>[20,24]
22+
<strong>解释:</strong>
23+
列表 1:[4, 10, 15, 24, 26],24 在区间 [20,24] 中。
24+
列表 2:[0, 9, 12, 20],20 在区间 [20,24] 中。
25+
列表 3:[5, 18, 22, 30],22 在区间 [20,24] 中。
26+
</pre>
27+
28+
<p><strong>示例 2:</strong></p>
29+
30+
<pre>
31+
<strong>输入:</strong>nums = [[1,2,3],[1,2,3],[1,2,3]]
32+
<strong>输出:</strong>[1,1]
33+
</pre>
34+
35+
<p>&nbsp;</p>
36+
37+
<p><strong>提示:</strong></p>
38+
39+
<ul>
40+
<li><code>nums.length == k</code></li>
41+
<li><code>1 &lt;= k &lt;= 3500</code></li>
42+
<li><code>1 &lt;= nums[i].length &lt;= 50</code></li>
43+
<li><code>-10<sup>5</sup> &lt;= nums[i][j] &lt;= 10<sup>5</sup></code></li>
44+
<li><code>nums[i]</code> 按非递减顺序排列</li>
45+
</ul>
46+
47+
<p>&nbsp;</p>
48+
49+
50+
51+
## 解题方法:优先队列
52+
53+
使用一个优先队列,每个“整数列表”放一个元素到优先队列中,优先队列以“列表元素最小”为最优先。
54+
55+
优先队列中存放的,是每个列表本次要覆盖的元素。
56+
57+
每次从优先队列中取出一个元素:
58+
59+
> 那么这次方案(取出之前)的最小值就是取出的这个元素,最大值我们使用一个值记录并在入队时候更新。
60+
>
61+
> 更新最佳方案:如果当前方案优于之前的最佳方案,就更新最佳方案为这个方案。
62+
>
63+
> 新元素入队:如果出队元素所在列表还有新元素,则下一个元素入队,并记得更新“最大值”;否则结束循环。
64+
65+
+ 时间复杂度$O(nk\log k)$
66+
+ 空间复杂度$O(k)$
67+
68+
### AC代码
69+
70+
#### C++
71+
72+
```cpp
73+
class Solution {
74+
public:
75+
vector<int> smallestRange(vector<vector<int>>& nums) {
76+
vector<int> loc(nums.size());
77+
auto cmp = [&nums, &loc](const int& x, const int& y) {
78+
return nums[x][loc[x]] > nums[y][loc[y]];
79+
};
80+
priority_queue<int, vector<int>, decltype(cmp)> pq(cmp);
81+
int m = -1e8, M = -1e6;
82+
for (int i = 0; i < nums.size(); i++) {
83+
pq.push(i);
84+
M = max(M, nums[i][0]);
85+
}
86+
int nowm, nowM = M;
87+
while (pq.size()) {
88+
int index = pq.top();
89+
pq.pop();
90+
nowm = nums[index][loc[index]];
91+
loc[index]++;
92+
if (nowM - nowm < M - m) {
93+
M = nowM;
94+
m = nowm;
95+
}
96+
if (loc[index] == nums[index].size()) {
97+
break;
98+
}
99+
nowM = max(nowM, nums[index][loc[index]]);
100+
pq.push(index);
101+
}
102+
return {m, M};
103+
}
104+
};
105+
```
106+
107+
> 同步发文于CSDN和我的[个人博客](https://blog.letmefly.xyz/),原创不易,转载经作者同意后请附上[原文链接](https://blog.letmefly.xyz/2024/11/24/LeetCode%200632.%E6%9C%80%E5%B0%8F%E5%8C%BA%E9%97%B4/)哦~
108+
>
109+
> Tisfy:[https://letmefly.blog.csdn.net/article/details/144011635](https://letmefly.blog.csdn.net/article/details/144011635)

Solutions/Other-English-LearningNotes-SomeWords.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -820,6 +820,9 @@ tags: [其他, 知识, 英语, Notes]
820820
|hydraulic|adj. 水力的,水压的,液压驱动的|
821821
|curtail|v. 缩短,限制,减缩|
822822
|colonel|n. (陆军/海军陆战队/美国空军)上校|
823+
|||
824+
|walnut|n. 核桃,胡桃,胡桃木,胡桃色|
825+
|smack|v. 用巴掌打,掴,啪的一声使劲放(或扔、甩等),使劲碰(或撞)<br/>n. 打巴掌,(打出的)一拳,啪的一声;海洛因<br/>adv. 恰好,直接,不偏不倚地,猛地|
823826

824827
<p class="wordCounts">单词收录总数</p>
825828

Solutions/Other-Japanese-LearningNotes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1074,6 +1074,7 @@ xx型
10741074
|もう夏になりました。<br/>已经夏天了。|
10751075
|外国に行ったことがありますか?<br/>去过外国吗?|
10761076
|明日映画を見るつもりです。<br/>明天打算去看电影。|
1077+
|今年はカナダに行くつもりです。<br/>今年打算去加拿大。|
10771078
|このアニメを<font color="#28bea0">見たこと</font>があります。<br/>看过这个动漫。|
10781079
|段々暖かく<font color="#ce82ff">なり</font>ました。<br/>越来越暖和了。|
10791080
|その<ruby>後<rt>go</rt></ruby>、映画館に行きました。<br/>那之后去了电影院。|

0 commit comments

Comments
 (0)