Java实现 LeetCode 632 最小区间(又是先序队列,官方给的是堆)
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 最小区间(又是先序队列,官方给的是堆)的更多相关文章
- Leetcode 632.最小区间
最小区间 你有 k 个升序排列的整数数组.找到一个最小区间,使得 k 个列表中的每个列表至少有一个数包含在其中. 我们定义如果 b-a < d-c 或者在 b-a == d-c 时 a < ...
- Java实现 LeetCode 539 最小时间差(单位转换)
539. 最小时间差 给定一个 24 小时制(小时:分钟)的时间列表,找出列表中任意两个时间的最小时间差并已分钟数表示. 示例 1: 输入: ["23:59","00:0 ...
- Java实现 LeetCode 453 最小移动次数使数组元素相等
453. 最小移动次数使数组元素相等 给定一个长度为 n 的非空整数数组,找到让数组所有元素相等的最小移动次数.每次移动可以使 n - 1 个元素增加 1. 示例: 输入: [1,2,3] 输出: 3 ...
- Java实现 LeetCode 310 最小高度树
310. 最小高度树 对于一个具有树特征的无向图,我们可选择任何一个节点作为根.图因此可以成为树,在所有可能的树中,具有最小高度的树被称为最小高度树.给出这样的一个图,写出一个函数找到所有的最小高度树 ...
- Java实现 LeetCode 228 汇总区间
228. 汇总区间 给定一个无重复元素的有序整数数组,返回数组区间范围的汇总. 示例 1: 输入: [0,1,2,4,5,7] 输出: ["0->2","4-> ...
- Java实现 LeetCode 155 最小栈
155. 最小栈 设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈. push(x) – 将元素 x 推入栈中. pop() – 删除栈顶的元素. top() – 获取 ...
- Java实现 LeetCode 64 最小路径和
64. 最小路径和 给定一个包含非负整数的 m x n 网格,请找出一条从左上角到右下角的路径,使得路径上的数字总和为最小. 说明:每次只能向下或者向右移动一步. 示例: 输入: [ [1,3,1], ...
- Java实现 LeetCode 57 插入区间
57. 插入区间 给出一个无重叠的 ,按照区间起始端点排序的区间列表. 在列表中插入一个新的区间,你需要确保列表中的区间仍然有序且不重叠(如果有必要的话,可以合并区间). 示例 1: 输入: inte ...
- Java实现 LeetCode 56 合并区间
56. 合并区间 给出一个区间的集合,请合并所有重叠的区间. 示例 1: 输入: [[1,3],[2,6],[8,10],[15,18]] 输出: [[1,6],[8,10],[15,18]] 解释: ...
随机推荐
- [hdu1402]大数乘法(FFT模板)
题意:大数乘法 思路:FFT模板 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 ...
- python --字符串学习
一 转义字符 借用一个特殊的方法表示一系列不方便写出的内容,比如回车键,换行符,退格键 借助反斜杠字符,一旦出现反斜杠,则反斜杠后面一个或者几个字符表示已经不是原来的意思了 在字符串中,一旦出现了斜杠 ...
- Docker学习笔记(二):端口映射与容器互联
端口映射 使用docker run时,可以指定-P(大写)与-p(小写)参数映射端口. docker run -P -P(大写)会随机映射一个端口到容器的内部端口 -> [feifei@ffma ...
- ql的python学习之路-day15
前言:本节主要讲解的是文件路径 在实际的软件开发中会设计一个项目的文件目录,按照执行包bin.配置包config.核心包core等来设计,在执行包里面要运行核心包里的主程序mian,由于不在同一级的目 ...
- The Apache Tomcat Connector
http://tomcat.apache.org/connectors-doc/generic_howto/quick.html 搭建最简单的tomcat connector 用到了apapche 的 ...
- 【雕爷学编程】Arduino动手做(6)---声音传感器模块
37款传感器的提法,在网络上广泛流传,其实Arduino能够兼容的传感器模块肯定是不止37种的.鉴于本人手头积累了一些传感器,依照实践(动手试试)出真知的理念,以学习和交流为目的,这里准备逐一做做实验 ...
- react+express实现跨域
1. 首先复习一下跨域的几种主要方式: a. jsonp b. cors c. 代理服务(开发环境下常用) 2. 代理服务器:可实现转发请求.即浏览器在3000端口发出请求,通过代理转发,将请求发送给 ...
- linux_centos7_时间更新
EDT:美国时间 CST:中国北京时间 方法一.使用ntpdate从时间服务器更新时间: 1.下载ntpdate组件 yum install -y ntp 2.完成后直接测试 [ ...
- Vue零基础入门记录
在2020年这个开局不利的年份毕业,实习工作都很难得.最近来到一家单位,为了减小开支实习生过来了的话前端后端都要写.用Vue和ElementUI做界面.以前的前端vue了解还停留在new一个Vue实例 ...
- 蓝桥杯 试题 算法提高 宰羊 DP解决
问题描述 炫炫回了内蒙,肯定要吃羊肉啦,所有他家要宰羊吃. 炫炫家有N只羊,羊圈排成一排,标号1~N.炫炫每天吃掉一只羊(这食量!其实是放生啦),吃掉的羊的邻居会以为它被放生了,然后又会告诉他们的邻居 ...