你有 k 个升序排列的整数数组。找到一个最小区间,使得 k 个列表中的每个列表至少有一个数包含在其中。
我们定义如果 b-a < d-c 或者在 b-a == d-c 时 a < c,则区间 [a,b] 比 [c,d] 小。
示例 1:
输入:[[4,10,15,24,26], [0,9,12,20], [5,18,22,30]]
输出: [20,24]
解释:
列表 1:[4, 10, 15, 24, 26],24 在区间 [20,24] 中。
列表 2:[0, 9, 12, 20],20 在区间 [20,24] 中。
列表 3:[5, 18, 22, 30],22 在区间 [20,24] 中。
代码
class Solution {class numG{int g,num;public numG(int g,int num){this.g=g;this.num=num;}}public int[] smallestRange(List<List<Integer>> nums) {PriorityQueue<numG> priorityQueue=new PriorityQueue<>(((o1, o2) -> o1.num-o2.num));
//维护最小堆int end=Integer.MIN_VALUE;int[] index=new int[nums.size()];//记录每个序列的指针for(int i=0;i<nums.size();i++){if(nums.get(i).get(0)>end) end=nums.get(i).get(0);//找出起始区间numG temp=new numG(i,nums.get(i).get(0));priorityQueue.offer(temp);//将每个序列首元素入队}int max=end;int start=priorityQueue.peek().num;int min=start;//初始区间int len=end-start+1;//区间长度while (true){int gr=priorityQueue.poll().g;//将最小的数值出队if (index[gr]+1==nums.get(gr).size()) break;//已经到了该序列的末尾了index[gr]++;//指向该序列的下一个numG n=new numG(gr,nums.get(gr).get(index[gr]));//将下一个入队priorityQueue.offer(n);max= Math.max(max,n.num);//区间扩大min=priorityQueue.peek().num;if(max-min+1<len)//如果是更短的区间,则替换掉原来的区间{start=max;end=min;len=max-min+1;}}return new int[]{end,start};}
}