题目描述:
思路:完全没思路。。看了题解给出了两种做法。1.用多指针。 2.用滑动窗口
1.多指针:一开始看多指针又是多指针又要用到最小堆排序感觉很难,但是深入发现,思想还是很好理解的。首先用k个指针来表示指向k个list中的第一个元素,计算此时的最大最小值,此时的range与全局的最大最小值形成的range进行比较。如果此时range更小,那么更新全局的最大最小值。不断右移最小元素所在list 的指针重复上面操作,直到有指针到达最后一个元素。其中前面提到的最小堆是用来找到当前k个指针中最小元素所在的list。
附上官方代码:
class Solution {
public int[] smallestRange(List<List<Integer>> nums) {
int rangeLeft = 0, rangeRight = Integer.MAX_VALUE;
int minRange = rangeRight - rangeLeft;
int max = Integer.MIN_VALUE;
int size = nums.size();
int[] next = new int[size];
PriorityQueue<Integer> priorityQueue = new PriorityQueue<Integer>(new Comparator<Integer>() {
public int compare(Integer index1, Integer index2) {
return nums.get(index1).get(next[index1]) - nums.get(index2).get(next[index2]);
}
});
for (int i = 0; i < size; i++) {
priorityQueue.offer(i);
max = Math.max(max, nums.get(i).get(0));
}
while (true) {
int minIndex = priorityQueue.poll();
int curRange = max - nums.get(minIndex).get(next[minIndex]);
if (curRange < minRange) {
minRange = curRange;
rangeLeft = nums.get(minIndex).get(next[minIndex]);
rangeRight = max;
}
next[minIndex]++;
if (next[minIndex] == nums.get(minIndex).size()) {
break;
}
priorityQueue.offer(minIndex);
max = Math.max(max, nums.get(minIndex).get(next[minIndex]));
}
return new int[]{rangeLeft, rangeRight};
}
}
2.滑动窗口:
[1 0 2]1 0 1 0 2 1 2 0 0 2 [0, 5]
1[0 2 1]0 1 0 2 1 2 0 0 2 [0, 5]
1 0[2 1 0]1 0 2 1 2 0 0 2 [0, 5]
1 0[2 1 0 1]0 2 1 2 0 0 2 [0, 5]
1 0[2 1 0 1 0]2 1 2 0 0 2 [0, 5]
1 0 2 1 0[1 0 2]1 2 0 0 2 [0, 5]
1 0 2 1 0 1[0 2 1]2 0 0 2 [0, 5]
1 0 2 1 0 1[0 2 1 2]0 0 2 [0, 5]
1 0 2 1 0 1 0 2[1 2 0]0 2 [20, 24]
1 0 2 1 0 1 0 2[1 2 0 0]2 [20, 24]
1 0 2 1 0 1 0 2[1 2 0 0 2] [20, 24]
官方代码:
class Solution {
public int[] smallestRange(List<List<Integer>> nums) {
int size = nums.size();
Map<Integer, List<Integer>> indices = new HashMap<Integer, List<Integer>>();
int xMin = Integer.MAX_VALUE, xMax = Integer.MIN_VALUE;
for (int i = 0; i < size; i++) {
for (int x : nums.get(i)) {
List<Integer> list = indices.getOrDefault(x, new ArrayList<Integer>());
list.add(i);
indices.put(x, list);
xMin = Math.min(xMin, x);
xMax = Math.max(xMax, x);
}
}
int[] freq = new int[size];
int inside = 0;
int left = xMin, right = xMin - 1;
int bestLeft = xMin, bestRight = xMax;
while (right < xMax) {
right++;
if (indices.containsKey(right)) {
for (int x : indices.get(right)) {
freq[x]++;
if (freq[x] == 1) {
inside++;
}
}
while (inside == size) {
if (right - left < bestRight - bestLeft) {
bestLeft = left;
bestRight = right;
}
if (indices.containsKey(left)) {
for (int x: indices.get(left)) {
freq[x]--;
if (freq[x] == 0) {
inside--;
}
}
}
left++;
}
}
}
return new int[]{bestLeft, bestRight};
}
}