方法一:滑动窗口
class Solution { public int[] smallestRange(List<List<Integer>> nums) { int size = nums.size(); Map<Integer,List<Integer>> map = new HashMap<>(); int min = Integer.MAX_VALUE, max = Integer.MIN_VALUE; for(int i = 0; i < size; i++) { for(int num : nums.get(i)) { map.computeIfAbsent(num,k->new ArrayList<>()).add(i); min = Math.min(min,num); max = Math.max(max,num); } } int[] pos = new int[size]; int left = min, right = min; int l = min, r = max; int count = 0; // 窗口覆盖区间个数 while(right <= max) { if(map.containsKey(right)) { for(int p : map.get(right)) { if(pos[p]++ == 0) count++; } while(count == size) { if(right - left < r - l) { r = right; l = left; } if(map.containsKey(left)) { for(int p : map.get(left)) { if(--pos[p] == 0) count--; } } left++; } } right++; } return new int[]{l,r}; } }
方法二:优先队列
class Solution { public int[] smallestRange(List<List<Integer>> nums) { int n = nums.size(), max = Integer.MIN_VALUE; int[] res = new int[]{Integer.MIN_VALUE/3,Integer.MAX_VALUE/3}; PriorityQueue<int[]> queue = new PriorityQueue<>((o1,o2)->(o1[0]-o2[0]));// 保存每个区间的最小值,区间编号,区间索引 for(int i = 0; i < n; i++) { // 初始化优先队列 List<Integer> list = nums.get(i); int[] val = new int[]{list.get(0),i,0}; queue.add(val); max = Math.max(max,list.get(0)); } while(true) { int[] q = queue.poll(); if(max - q[0] < res[1] - res[0]) { res[1] = max; res[0] = q[0]; } int index = ++q[2]; if(index >= nums.get(q[1]).size()) break; // 指针越界就退出 int[] newQ = new int[]{nums.get(q[1]).get(index),q[1],index}; queue.add(newQ); max = Math.max(max,nums.get(q[1]).get(index)); // 更新最大值 } return res; } }