你有 k 个 非递减排列 的整数列表。找到一个 最小 区间,使得 k 个列表中的每个列表至少有一个数包含在其中。
我们定义如果 b-a < d-c 或者在 b-a == d-c 时 a < c,则区间 [a,b] 比 [c,d] 小。
示例 1:
输入:nums = [[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] 中。
示例 2:
输入:nums = [[1,2,3],[1,2,3],[1,2,3]]
输出:[1,1]
提示:
nums.length == k
1 <= k <= 3500
1 <= nums[i].length <= 50
-105 <= nums[i][j] <= 105
nums[i] 按非递减顺序排列
思路梳理:
把三个数组合到一起真的很难想啊www
合到一起并多记录所属组别的序号
这样就可以转换到滑动窗口去解决这个问题
滑动窗口
想到这里就可以考虑是先移动左坐标还是先移动右坐标。
emmmmm一开始想的先移动左坐标我也不知道自己怎么想的阿巴巴
发现思路梳理不清,翻看答案发现都是先移动j
设计:
j的组别数放入集合中,判断是否是第一次放入,如果是就k++
如果k==组别总数,说明满足题目条件,就可以计算了
但有一种情况是
0 1 0 0 2 这种情况前面的0就是多余的
因此我们加入一个while来吃掉前面多余的0,直到第一个数出现次数为1
然后就更新答案记录答案就可
因为答案是提交一个vector集合,故注意特判集合为空,以及生成新的集合来更新答案
class Solution {
public:
vector<int> smallestRange(vector<vector<int>>& nums) {
vector<pair<int, int>> ord;
for (int k = 0; k < nums.size(); ++k)
for (auto n: nums[k]) ord.push_back({n, k});
sort(ord.begin(), ord.end());
int i = 0, k = 0;
vector<int> ans;
map<int, int> count;
for (int j = 0; j < ord.size(); ++j) {
count[ord[j].second]++;
if ( count[ord[j].second]==1){
++k;
}
if (k == nums.size()) {
while (count[ord[i].second] > 1) --count[ord[i++].second];
if (ans.empty() || ans[1] - ans[0] > ord[j].first - ord[i].first) {
ans = {ord[i].first, ord[j].first};
}
}
}
return ans;
}
};