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.
最小区间。题意是给一个list of list,sublist里面都是整数,且每个sublist都是有序的。请返回一个最小区间,使得input里的每个sublist至少有一个元素在这个最小区间里。
这道题我是用priority queue做的。这道题其实还有滑动窗口的做法,我之后再补充吧。
我们照着这个例子讲一下思路,
Input: [[4,10,15,24,26], [0,9,12,20], [5,18,22,30]]
因为每个sublist都是有序的,所以可以先把每个sublist的第一个元素加入一个以priority queue创建的最小堆,这样,最小的元素始终在堆顶。在把所有sublist的第一个元素加入pq之后,同时也得到了一个第一个区间[0, 5]。
接着开始往后遍历,因为第一个区间是[0, 5],如果想试着缩小这个区间,那么要不然就是提高下限要不然就是提高上限。因为所有的sublist都是递增的所以只能试着提高下限。因为0又是堆顶元素,所以去掉0,加入0所在的sublist之后的那个数字9。此时pq里是[4, 5, 9],同时最大元素是9,最小元素是4,新的区间是[4, 9],区间并没有比之前小,不更新。
第三轮,此时因为堆顶元素是4,所以弹出4,加入4之后的那个元素10,此时pq里面是[5, 9, 10],新的区间是[5, 10],区间并没有比之前小,不更新。
第四轮,堆顶元素是5,弹出5,加入5之后的那个元素18,此时pq里面是[9, 10, 18],区间并没有比之前小,不更新。
第五轮,堆顶元素9,弹出9,加入9之后的那个元素12,此时pq里面是[10, 12, 18],区间并没有比之前小,不更新。
第六轮,堆顶元素10,弹出10,加入10之后的那个元素15,此时pq里面是[12, 15, 18],区间并没有比之前小,不更新。
……
照着这个方式去遍历,把所有sublist里面的数字都通过pq过滤一遍,最后会得到最小的区间[20, 24]。
时间O(nlogk)
空间O(k)
Java实现
1 class Solution { 2 public int[] smallestRange(List> nums) { 3 // corner case 4 if (nums == null || nums.size() == 0) { 5 return new int[0]; 6 } 7 8 // normal case 9 int[] res = new int[2]; 10 PriorityQueue<int[]> minHeap = new PriorityQueue<>((a, b) -> a[0] - b[0]); 11 int max = Integer.MIN_VALUE; 12 int minLen = Integer.MAX_VALUE; 13 int n = nums.size(); 14 for (int i = 0; i < n; i++) { 15 int num = nums.get(i).get(0); 16 minHeap.add(new int[] { num, i, 0 }); 17 max = Math.max(max, num); 18 } 19 20 while (minHeap.size() == n) { 21 int[] cur = minHeap.poll(); 22 if (max - cur[0] < minLen) { 23 minLen = max - cur[0]; 24 res[0] = cur[0]; 25 res[1] = max; 26 } 27 if (cur[2] < nums.get(cur[1]).size() - 1) { 28 int num = nums.get(cur[1]).get(cur[2] + 1); 29 minHeap.add(new int[] { num, cur[1], cur[2] + 1 }); 30 max = Math.max(max, num); 31 } 32 } 33 return res; 34 } 35 }
LeetCode 题目总结