原题:https://leetcode.com/problems/smallest-range/description/
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:
1.he given list may contain duplicates, so ascending order means >= here.
2.1 <= k <= 3500
3.-105 <= value of elements <= 105.
4.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.
next矩阵是一个链表,由每一行中的一个数组成。
next矩阵中每个元素的值代表其对应的列坐标。如next[2] == 3,那么next[2]就代表第三行第四列的数。
min_i对应的是当前next矩阵中坐标对应的值中最小值的行坐标。
举例: nums[2][3]是最小值,此时next[2]应该等于3
而这个时候的min_i的值等于2
1.建立一个next矩阵,矩阵长度为nums.size(),且全部初始化为0.
2.找到next矩阵中的最小最大值。
3.创建循环,每次都取出当前next中min_i对应的元素。将其和最大值组成的范围和之前的范围相比较。
4.如果新生成的范围比之前小,那么更新范围为当前最小最大值。
5.更新当前最小值对应next中的值。并将先前最大值和更新的next[min_i]对应的值比较,MAX = max(MAX, nums[min_i][next[min_i]]);
6.直到有一行被遍历完之前,重复2-5步。
为了减少每次查找next中元素对应的值的最小值的时间,利用priority_queue建立一个最小堆。堆中元素为pair< int,int>。由next[min_i]和nums[min_i][next[min_i]]组成
每次取出最顶上的数也就是当前next对应的数值中的最小值,再得到其对应的next中的位置,也就是min_i。然后将取出的pair从堆中删除。在经历上述的3,4,5步后,将更新后的 min_i对应的数对pair加到堆中。
循环完成后将得到的范围返回。
#include <iostream>
#include <vector>
#include<functional>
#include <limits>
#include<queue>
#include <algorithm>
using namespace std;
class Solution {
public:
vector<int> smallestRange(vector<vector<int>>& nums) {
int x = 0, y = INT_MAX, MAX = INT_MIN, min_i = 0;
bool flag = 1;
vector<int> next(nums.size());
struct cmp {
bool operator()(pair<int, int> p1, pair<int, int> p2) {
return p1.second > p2.second;
}
};
priority_queue<pair<int, int>, vector<pair<int, int>>, cmp > p;
for (int i = 0; i < nums.size(); i++) {
next[i] = 0;
p.push(make_pair(i, nums[i][0]));
MAX = max(MAX, nums[i][0]);
}
while(flag) {
int min_i = p.top().first;
p.pop();
if (y - x > MAX - nums[min_i][next[min_i]]) {
x = nums[min_i][next[min_i]];
y = MAX;
}
next[min_i]++;
if (next[min_i] == nums[min_i].size()) {
flag = false;
break;
}
p.push(make_pair(min_i, nums[min_i][next[min_i]]));
MAX = max(MAX, nums[min_i][next[min_i]]);
}
return vector<int>({x, y});
}
};
int main() {
Solution s;
vector<vector<int> > v = { {4,10,15,24,26},{0,9,12,20},{5,18,22,30} };
vector<int> z = s.smallestRange(v);
cout << z[0] << " " << z[1] << endl;
}
86 / 86 test cases passed.
Status: Accepted
Runtime: 39 ms