632. Smallest Range

You have k lists of sorted integers in ascending order. Find the smallest range that includes at least one number from each of thek 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. The 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.

思路:遇到这题,我一开始就想 想出最优解,然后想到用Binary Search,毕竟是满足一定条件下求最值问题,但是后面一直WA,主要是因为是求范围,有2个变量在变

后面看Discuss里面先尝试用Brute force然后慢慢优化到最优解,发现想不出来还是得一步步慢慢来
Brute force 就是枚举了,每个数组都取出一个数,然后用一个范围包括这些数。主要在枚举过程中记录最小的range就OK了
想到这里应该可以联想到用优先队列来减小这个枚举过程的重复计算量,其具体过程类似于merge K个数组一样

package l632;

import java.util.Comparator;
import java.util.List;
import java.util.PriorityQueue;

/*
 * 先往Brute force想,就是遍历每个数组拿出一个
 * 肯定重复计算很多,所以然后再考虑优化
 * 
 * 从每个数组中取出一个放到一个最小堆,用一个范围包括这些数字不就是一个合理的range了
 * 每次就从抽出来的数中拿出最小的那个数,然后再加入在那个数组里面后面的那个数
 * 当加不了时就结束了,在这个过程中收集range最小的答案
 */
public class Solution {
    public int[] smallestRange(List<List<Integer>> nums) {
    	PriorityQueue<int[]> minHeap = new PriorityQueue<int[]>(nums.size(), new Comparator<int[]>(){
			public int compare(int[] o1, int[] o2) {
				return o1[0] - o2[0];
			}
    	});
    	
    	int max = nums.get(0).get(0);
    	for(int i=0; i<nums.size(); i++) {
    		minHeap.add(new int[]{nums.get(i).get(0), i, 0});
    		max = Math.max(max, nums.get(i).get(0));
    	}
    	
    	int minRange = Integer.MAX_VALUE;
    	int start = -1;
    	while(minHeap.size() == nums.size()) {
    		int[] t = minHeap.poll();
    		if(max - t[0] < minRange) {
    			minRange = max - t[0];
    			start = t[0];
    		}
    		
    		if(t[2]+1 < nums.get(t[1]).size()) {
    			t[0] = nums.get(t[1]).get(t[2]+1);
    			t[2] ++;
    			minHeap.add(t);
    			max = Math.max(max, t[0]);
    		}
    	}
    	
    	return new int[]{start, start+minRange};
	}
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值