632. 最小区间

你有 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] 中。

注意:

给定的列表可能包含重复元素,所以在这里升序表示 >= 。

1 <= k <= 3500

-105 <= 元素的值 <= 105

对于使用Java的用户,请注意传入类型已修改为List<List>。重置代码模板后可以看到这项改动。

class Solution {
public int[] smallestRange(List<List<Integer>> nums) {
if(nums == null || nums.size() == 0)
return null;
int len = nums.size();
PriorityQueue<Pair> queue = new PriorityQueue<>(Comparator.comparingInt(p -> p.num));
int[] res = new int[2];
res[1] = Integer.MAX_VALUE;
//maxNum 记录每一次遍历中k个数组的最大值
int maxNum = Integer.MIN_VALUE;
//初始化优先队列,将k个数组的第一个数字入队
for(int i = 0;i<len;i++){
int num = nums.get(i).get(0);
maxNum = Math.max(maxNum,num);
queue.add(new Pair(i,0,num));
}
//这里的循环退出条件是队列为空,也可以写成双层循环遍历数组
while(!queue.isEmpty()){
//每次遍历,先从队列中取出当前最小值
Pair pair = queue.poll();
int num = pair.num;
//如果(当前最小值,当前最大值)的区间范围更小,则修改res数组
if(res[1] - res[0] > maxNum - num){
res[0] = num;
res[1] = maxNum;
}
int row = pair.row;
//右移
int col = pair.col + 1;
//如果右移后超出数组长度,此时退出循环,即已经找到最小的区间了
if(nums.get(row).size() == col){
break;
}
//下一个数,是当前数右边的数
int nextNum = nums.get(row).get(col);
//下一个数继续入队列
queue.add(new Pair(row,col,nextNum));
//更新当前最大值
maxNum = Math.max(maxNum,nextNum);
}
return res;
}
//定义一个类,用来记录遍历过程中,每个数字所在的行、列和数字对应的值
class Pair{
public Integer row;
public Integer col;
public Integer num;
public Pair(Integer row,Integer col,Integer num){
this.row = row;
this.col = col;
this.num = num;
}
}
}

官方的解法

class Solution {
public int[] smallestRange(List<List<Integer>> nums) {
int minx = 0, miny = Integer.MAX_VALUE, max = Integer.MIN_VALUE;
int[] next = new int[nums.size()];
boolean flag = true;
// 最小堆维护的是当前的最小值,在哪个列表中。注意该堆的比较器。
PriorityQueue<Integer> min_queue = new PriorityQueue<Integer>((i,j) -> nums.get(i).get(next[i])-nums.get(j).get(next[j]));
// 初始化堆
for(int i=0;i<nums.size();i++){
min_queue.offer(i);
max = Math.max(max,nums.get(i).get(0));
}
// 从堆中取得当前最小元素所在的列表。根据next[i],取得其所在位置,多路指针法,类似于丑数;
// 经前面分期,第二个列表就是min_i在其列表的后一位及其之前其他数字组成的区间。最小值由最小堆(决定min_i)及next[min_i]维护,
// 最大值由max = Math.max(max, nums.get(min_i).get(next[min_i]))维护。 for(int i=0;i<nums.size()&&flag;i++){
for(int j=0;j<nums.get(i).size()&&flag;j++){
int min_i = min_queue.poll();
// 选择更小的区间
if(miny-minx> max - nums.get(min_i).get(next[min_i])){
miny = max;
minx = nums.get(min_i).get(next[min_i]);
}
// 由于next改变,min_i加入堆后,堆结构也会改变
next[min_i]++;
if(next[min_i]>=nums.get(min_i).size()){
flag = false;
break;
}
min_queue.offer(min_i);
max = Math.max(max, nums.get(min_i).get(next[min_i]));
}
}
return new int[]{minx,miny};
}
}

Java实现 LeetCode 632 最小区间(又是先序队列,官方给的是堆)的更多相关文章

  1. Leetcode 632.最小区间

    最小区间 你有 k 个升序排列的整数数组.找到一个最小区间,使得 k 个列表中的每个列表至少有一个数包含在其中. 我们定义如果 b-a < d-c 或者在 b-a == d-c 时 a < ...

  2. Java实现 LeetCode 539 最小时间差(单位转换)

    539. 最小时间差 给定一个 24 小时制(小时:分钟)的时间列表,找出列表中任意两个时间的最小时间差并已分钟数表示. 示例 1: 输入: ["23:59","00:0 ...

  3. Java实现 LeetCode 453 最小移动次数使数组元素相等

    453. 最小移动次数使数组元素相等 给定一个长度为 n 的非空整数数组,找到让数组所有元素相等的最小移动次数.每次移动可以使 n - 1 个元素增加 1. 示例: 输入: [1,2,3] 输出: 3 ...

  4. Java实现 LeetCode 310 最小高度树

    310. 最小高度树 对于一个具有树特征的无向图,我们可选择任何一个节点作为根.图因此可以成为树,在所有可能的树中,具有最小高度的树被称为最小高度树.给出这样的一个图,写出一个函数找到所有的最小高度树 ...

  5. Java实现 LeetCode 228 汇总区间

    228. 汇总区间 给定一个无重复元素的有序整数数组,返回数组区间范围的汇总. 示例 1: 输入: [0,1,2,4,5,7] 输出: ["0->2","4-> ...

  6. Java实现 LeetCode 155 最小栈

    155. 最小栈 设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈. push(x) – 将元素 x 推入栈中. pop() – 删除栈顶的元素. top() – 获取 ...

  7. Java实现 LeetCode 64 最小路径和

    64. 最小路径和 给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小. 说明:每次只能向下或者向右移动一步. 示例: 输入: [ [1,3,1], ...

  8. Java实现 LeetCode 57 插入区间

    57. 插入区间 给出一个无重叠的 ,按照区间起始端点排序的区间列表. 在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间). 示例 1: 输入: inte ...

  9. Java实现 LeetCode 56 合并区间

    56. 合并区间 给出一个区间的集合,请合并所有重叠的区间. 示例 1: 输入: [[1,3],[2,6],[8,10],[15,18]] 输出: [[1,6],[8,10],[15,18]] 解释: ...

随机推荐

  1. properties文件导出

    功能要求根据数据库记录的key-value-remark 数据,导出保存properties文件 1. pro.load()  pro.list() 处理不能解决备注.排序问题 2. 最后考虑下什么是 ...

  2. R语言:日薪和应发工资

    生产部门普通员工为日薪,有时要知道日薪和应发工资的转换关系.做表一为日薪取整数,白天工资+晚上工资=应发工资,延长工作时间取时薪的1.5倍,应发工资保留到十位.做表二为应发工资取十的倍数,推算相应日薪 ...

  3. Excel开始,Excel结束,R语言居中

    入职.离职,总公司调往分公司,分公司调往总公司,每月社保.公积金和上月比较有增减.税局导出的为Excel文件,需要和记录对照一番. 用Excel处理,那就是姓名粘贴为两列,条件格式-重复值,没变色的为 ...

  4. ES6,ES7,ES8 常用特性总结

    一. ES6(ES2015) 1. 变量 let 和常量 const var 的问题 可以重复声明,没有报错和警告 无法限制修改 没有块级作用域, { } let 和 const 不能重复声明 都是块 ...

  5. Docker在centos上的安装与常用命令大全

    docker的安装与加速器配置 安装docker:yum install docker (默认安装路径/var/lib/docker) 启动docker服务:systemctl start docke ...

  6. Reflux之Action

    reflux在flux的基础上,去掉了dispatcher. 在Reflux中,每一个Action本身就是一个Publisher(消息发布者),具有消息发布功能:而每一个Store除了作为数据存储之外 ...

  7. Jenkins-gogs安装及使用

    很多同学可能第一次了解什么是ci-cd,什么是Jenkins,首先会介绍下cicd的概念及应用场景,之后再详细介绍下Jenkins的概念.安装及使用. 什么是CI-CD? 首先明确CI-CD是一种技术 ...

  8. JSONObject转换为map

    http://cloudyxuq.iteye.com/blog/1618213 private static HashMap<String, String> toHashMap(Objec ...

  9. 马兴德201771010117《面向对象程序设计(java)》第一周学习总结

    第一部分:课程准备部分 填写课程学习 平台注册账号, 平台名称 注册账号 博客园:www.cnblogs.com 挽歌朽年 程序设计评测:https://pintia.cn/ 791683057@qq ...

  10. Unity实现byte[]合成图像

    bool CreateCovers(byte[] imageData) { Texture2D imageTexture = new Texture2D(273, 126); imageTexture ...