题目详情
你有 k 个升序排列的整数数组。找到一个最小区间,使得 k 个列表中的每个列表至少有一个数包含在其中。
我们定义如果 b-a < d-c 或者在 b-a == d-c 时 a < c,则区间 [a,b] 比 [c,d] 小。
示例 1:
输入:[[4,10,15,24,26], [0,9,12,20], [5,18,22,30]]
输出: [20,24]
解释:
列表 1:[4, 10, 15, 24, 26],24 在区间 [20,24] 中。
列表 2:[0, 9, 12, 20],20 在区间 [20,24] 中。
列表 3:[5, 18, 22, 30],22 在区间 [20,24] 中。
注意:
——题目难度:困难
首先把 nums 里的所有元素按 (number, group) 放进 ordered (vector
一开始有点对 "C++ sort对vector
>排序问题" 感到疑惑,后面找了资料发现 std::sort 在未指定比较方法时会使用 operator< 来比较元素,而 std::pair::operator< 按标准规定会在两个 std::pair 的第一个元素互不小于对方的情况下比较第二个元素(就是 _Right.first == _Left.first 的情况下,才比较第二个元素)。 以下代码来自 VS2017 RC 的 utility 文件:
template
inline constexpr bool operator<(const pair<_Ty1, _Ty2>& _Left, const pair<_Ty1, _Ty2>& _Right) { // test if _Left < _Right for pairs return (_Left.first < _Right.first || (!(_Right.first < _Left.first) && _Left.second < _Right.second)); } ——资料来源:C++ sort对vector
>排序问题
接着保证 ordered 在 [i, j] 里都有 nums.size() 个列表的至少一个元素,然后不断缩小区间,比如 只看所属组的的话,nums.size() = 3, 如果遇到 [1, 1, 2, 0] ,那么可以缩小成 [1, 2, 0];但如果遇到 [2, 1, 0, 1] ,那就不能缩小区间,因为区间得包括 nums.size() 个列表的至少一个元素,这样以此来得到最小区间。
更新 ans 的话 只需要 当满足 ans[1] - ans[0] > ordered[j].first - ordered[i].first 即可更新,这里不用考虑 当 "b-a == d-c
时 a < c
,则区间 [a,b] 比 [c,d] 小" 的情况,假如 ans = {a, b} 了, 且 d >= c >= b >= a,那么当 {c, d} 也符合条件,但 d - c == b - a,那就看 c 和 a,因为 i ,j 是从下标 0 开始往后遍历的,所以 c >= a:当 c == a,显然说明 d == b,那就说明 两个区间相同;如果 c > a,那么说明区间 [a,b] 比 [c,d] 小,那也没必要更新。
综上所述,更新 ans 的话 只需要 当满足 ans[1] - ans[0] > ordered[j].first - ordered[i].first 即可更新。
-解题代码如下
class Solution {
public:
vector smallestRange(vector>& nums) {
vector> ordered; // (number, group)
for(int i = 0; i < nums.size(); i++) {
for(int num : nums[i]) {
ordered.push_back({num, i});
}
}
sort(ordered.begin(), ordered.end());
int i = 0, k = 0; // i 为左边界
vector ans;
unordered_map count;
for(int j = 0; j < ordered.size(); j++) { // j 为右边界
if (!count[ordered[j].second]++) k++;
if (k == nums.size()) {
while (count[ordered[i].second] > 1) count[ordered[i++].second]--;
if (ans.empty() || ans[1] - ans[0] > ordered[j].first - ordered[i].first) {
ans = vector{ordered[i].first, ordered[j].first};
}
}
}
return ans;
}
};