description:
632 | Smallest Range | 42.2% | Hard |
You have k
lists of sorted integers in ascending order. Find the smallest range that includes at least one number from each of the k
lists.
We define the range [a,b] is smaller than range [c,d] if b-a < d-c
or a < c
if b-a == d-c
.
Example 1:
Input:[[4,10,15,24,26], [0,9,12,20], [5,18,22,30]] Output: [20,24] Explanation: List 1: [4, 10, 15, 24,26], 24 is in range [20,24]. List 2: [0, 9, 12, 20], 20 is in range [20,24]. List 3: [5, 18, 22, 30], 22 is in range [20,24].
Note:
- The given list may contain duplicates, so ascending order means >= here.
- 1 <=
k
<= 3500 - -105 <=
value of elements
<= 105. - For Java users, please note that the input type has been changed to List<List<Integer>>. And after you reset the code template, you’ll see this point.
my solution: 事实上这道题我没想出来要怎么解决……一开始我的思路是暴力求解,找出所有ans可能的排列组合然后再一一比较,但是这样所消耗的时间空间资源太大,所以并不适合这个题目。阅读了别人的解决方案。
better ways:
by Aeonaxx
#pragma once
#include<cstdio>
#include<string>
#include<string.h>
#include<vector>
#include<queue>
using namespace std;
class Solution {
public:
vector<int> smallestRange(vector<vector<int>>& nums) {
//构建迭代器
typedef vector<int>::iterator vi;
//构建comp用于比较,用于priority_queue<Type, Container, Functional>,小根堆,升序
struct comp {
bool operator()(pair<vi, vi> p1, pair<vi, vi> p2) {
return *p1.first > *p2.first;
}
};
int lo = INT_MAX, hi = INT_MIN;
//创建queue
priority_queue<pair<vi, vi>, vector<pair<vi, vi>>, comp> pq;
//初始化lo和hi,lo是每个队列的最小值,hi是每个队列开头的最大值
//把nums中每一个队列的开头和结束迭代器放入priority_queue中
for (auto &row : nums) {
lo = min(lo, row[0]);
hi = max(hi, row[0]);
pq.push({ row.begin(), row.end() });
}
vector<int> ans = { lo, hi };
while (true) {
auto p = pq.top();//取出堆顶队列
pq.pop();
++p.first;//原堆顶队列的下一个元素
if (p.first == p.second)
break;//如果队列已经全部遍历则终止
pq.push(p);//放回该队列
//如果区间缩小,则重新赋值
lo = *pq.top().first;//新堆顶元素
hi = max(hi, *p.first);//原堆顶元素
if (hi - lo < ans[1] - ans[0])
ans = { lo, hi };
}
return ans;
}
};
thought:
这个人的解法十分和谐方便,巧妙利用了stl,值得学习。