问题描述:
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.
解题思路:
首先我们将所有数组混合到一起,为了标识它原本属于哪个数组,我们用pair来存储,pair.first为数值, pair.second为它来自哪个数组。
然后我们用sort将其排序。
排序后可以用滑动窗口来解决这个问题。
即,找一个窗口两端差最小的窗口,窗口里的值必须每个链表中的至少一个值。
可以参考 76. Minimum Window Substring
不过将比较值设为v[i].first - v[l].first。
同时我们也用一个map来存储k个链表中的值的个数。
代码:
class Solution { public: vector<int> smallestRange(vector<vector<int>>& nums) { unordered_map<int, int> m; vector<pair<int,int>> v; vector<int> ret; for(int i = 0; i < nums.size(); i++){ for(int j = 0; j < nums[i].size(); j++){ v.push_back(pair<int,int>(nums[i][j], i)); } m[i] = 1; } sort(v.begin(), v.end()); int count = 0; int l = 0, len = INT_MAX; int k = nums.size(); for(int i = 0; i < v.size(); i++){ pair<int, int> p = v[i]; m[p.second]--; if(m[p.second] > -1) count++; while(count == k && l <= i){ if(len > (v[i].first - v[l].first)){ len = v[i].first - v[l].first; ret = {v[l].first, v[i].first}; } if(++m[v[l].second] == 1) count--; l++; } } return ret; } };