最小区间
时间:2022-07-22
本文章向大家介绍最小区间,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
问题描述:
你有 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
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/smallest-range-covering-elements-from-k-lists
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
解决方案
由题目可知,是想找到一个包含每个列表元素的子区间,即找到k个列表中尽可能接近的数,因此可以使用k路归并排序,排序过程中存储这k个列表当前元素的最小值与最大值,直到k个列表中某个列表元素全部用完,如此最小区间一定在遍历过的最小值最大值之中。
对于k个列表当前元素的最小值与最大值,直接遍历,即O(K),若数组长度记做N时,总体时间复杂度为(N * K * K),由于对每个元素均要扫描k次。
代码如下:
class Solution {
public int[] smallestRange(List<List<Integer>> nums) {
int left = (int)-1e5;
int right = (int)1e5;
int k = nums.size();
// 用于存储k个列表的当前位置
int[] curIndex = new int[k];
int max = 0;
int min = 0;
while(true){
for(int i = 0; i < k; i++){
List<Integer> temp = nums.get(i);
if(temp.get(curIndex[i]) > nums.get(max).get(curIndex[max])){
max = i;
}
if(temp.get(curIndex[i]) < nums.get(min).get(curIndex[min])){
min = i;
}
}
if(nums.get(max).get(curIndex[max]) - nums.get(min).get(curIndex[min]) < right - left){
right = nums.get(max).get(curIndex[max]);
left = nums.get(min).get(curIndex[min]);
}
if(++curIndex[min] == nums.get(min).size()){
break;
}
}
return new int[] {left, right};
}
}
直接TLE了,用堆优化喽。
对于k个列表的最小值,借助一大小为K的最小堆,每次从中弹出一最小值即为所求,弹出后再将其所在列表的下一个值加入堆中(由于弹出后需要知道该值属于哪个列表,因此不能直接在堆中存值,应存其所在的列表id)。对于最大值,由于是进行排序的因此使用一变量max保存当前堆中的最大值(入堆前判断即可)。由于借助了堆每次查找时间复杂度和插入时间复杂度均为O(log(K)),因此总体时间复杂度为O(N * K * log(K)).
代码如下:
class Solution {
public int[] smallestRange(List<List<Integer>> nums) {
int left = (int)-1e5;
int right = (int)1e5;
int k = nums.size();
int[] curIndex = new int[k];
int max = (int)-1e5;
Queue<Integer> minHeap = new PriorityQueue(new Comparator<Integer>(){
public int compare(Integer o1, Integer o2){
return nums.get(o1).get(curIndex[o1]) - nums.get(o2).get(curIndex[o2]);
}
});
for(int i = 0; i < k; i++){
minHeap.add(i);
max = Math.max(max, nums.get(i).get(0));
}
while(true){
int cur = minHeap.remove();
if(max - nums.get(cur).get(curIndex[cur]) < right - left){
right = max;
left = nums.get(cur).get(curIndex[cur]);
}
if(++curIndex[cur] == nums.get(cur).size()){
break;
}
max = Math.max(max, nums.get(cur).get(curIndex[cur]));
minHeap.add(cur);
}
return new int[] {left, right};
}
}
最后想谈一点的是,通过该问题还学习到了如此巧妙的内部类的用法。
- 51 Nod 1008 N的阶乘 mod P【Java大数乱搞】
- 【AlphaGo Zero 核心技术-深度强化学习教程代码实战06】给Agent添加记忆功能
- Gym 100952A&&2015 HIAST Collegiate Programming Contest A. Who is the winner?【字符串,暴力】
- [开源,学习,分享]UWP第三方简书客户端分享
- HDU 1024 Max Sum Plus Plus【动态规划求最大M子段和详解 】
- 51 Nod 1057 N的阶乘【Java大数乱搞】
- 2017 Multi-University Training Contest - Team 1 1011&&HDU 6043 KazaQ's Socks【规律题,数学,水】
- 2017 Multi-University Training Contest - Team 1 1001&&HDU 6033 Add More Zero【签到题,数学,水】
- 51 Nod 1005 大数加法【Java大数乱搞,python大数乱搞】
- 51 Nod 1029 大数除法【Java大数乱搞】
- 51 Nod 1027 大数乘法【Java大数乱搞】
- SQL常用的基础语法
- 51 Nod 1028 大数乘法 V2【Java大数乱搞】
- Gym 100952J&&2015 HIAST Collegiate Programming Contest J. Polygons Intersection【计算几何求解两个凸多边形的相交面积板子题
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Helm仓库的重要变更和v2支持将在11月结束
- ThinkPHP框架整合微信支付之刷卡模式图文详解
- 详解Python直接赋值,深拷贝和浅拷贝
- 利用python下载scihub成文献为PDF操作
- PHP中的Iterator迭代对象属性详解
- 使用Python实现微信拍一拍功能的思路代码
- Laravel5.7 Eloquent ORM快速入门详解
- 微信公众号用户与网站用户的绑定解决方案分析
- laravel使用Faker数据填充的实现方法
- PHP开发实现快递查询功能详解
- Laravel5.7 数据库操作迁移的实现方法
- PHP7引入的"??"和"?:"的区别讲解
- Python自动化操作实现图例绘制
- ThinkPHP5.0框架使用build 自动生成模块操作示例
- PHP远程连接oracle数据库操作实现方法图文详解