[LeetCode] 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 the k 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:
- The given list may contain duplicates, so ascending order means >= here.
- 1 <=
k<= 3500 - -105 <=
value of elements<= 105. - 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.
这道题给了我们一些数组,都是排好序的,让求一个最小的范围,使得这个范围内至少会包括每个数组中的一个数字。虽然每个数组都是有序的,但是考虑到他们之间的数字差距可能很大,所以最好还是合并成一个数组统一处理比较好,但是合并成一个大数组还需要保留其原属数组的序号,所以大数组中存pair对,同时保存数字和原数组的序号。然后重新按照数字大小进行排序,这样问题实际上就转换成了求一个最小窗口,使其能够同时包括所有数组中的至少一个数字。这不就变成了那道 Minimum Window Substring。所以说啊,这些题目都是换汤不换药的,总能变成我们见过的类型。这里用两个指针 left 和 right 来确定滑动窗口的范围,还要用一个 HashMap 来建立每个数组与其数组中数字出现的个数之间的映射,变量 cnt 表示当前窗口中的数字覆盖了几个数组,diff 为窗口的大小,让 right 向右滑动,然后判断如果 right 指向的数字所在数组没有被覆盖到,cnt 自增1,然后 HashMap 中对应的数组出现次数自增1,然后循环判断如果 cnt 此时为k(数组的个数)且 left 不大于 right,那么用当前窗口的范围来更新结果,然后此时想缩小窗口,通过将 left 向右移,移动之前需要减小 HashMap 中的映射值,因为去除了数字,如果此时映射值为0了,说明有个数组无法覆盖到了,cnt 就要自减1。这样遍历后就能得到最小的范围了,参见代码如下:
解法一:
class Solution {
public:
vector<int> smallestRange(vector<vector<int>>& nums) {
vector<int> res;
vector<pair<int, int>> v;
unordered_map<int, int> m;
for (int i = ; i < nums.size(); ++i) {
for (int num : nums[i]) {
v.push_back({num, i});
}
}
sort(v.begin(), v.end());
int left = , n = v.size(), k = nums.size(), cnt = , diff = INT_MAX;
for (int right = ; right < n; ++right) {
if (m[v[right].second] == ) ++cnt;
++m[v[right].second];
while (cnt == k && left <= right) {
if (diff > v[right].first - v[left].first) {
diff = v[right].first - v[left].first;
res = {v[left].first, v[right].first};
}
if (--m[v[left].second] == ) --cnt;
++left;
}
}
return res;
}
};
这道题还有一种使用 priority_queue 来做的,优先队列默认情况是最大堆,但是这道题我们需要使用最小堆,重新写一下 comparator 就行了。解题的主要思路很上面的解法很相似,只是具体的数据结构的使用上略有不同,这 curMax 表示当前遇到的最大数字,用一个 idx 数组表示每个 list 中遍历到的位置,然后优先队列里面放一个pair,是数字和其所属list组成的对儿。遍历所有的list,将每个 list 的首元素和该 list 序号组成 pair 放入队列中,然后 idx 数组中每个位置都赋值为1,因为0的位置已经放入队列了,所以指针向后移一个位置,还要更新当前最大值 curMax。此时 queue 中是每个 list 各有一个数字,由于是最小堆,所以最小的数字就在队首,再加上最大值 curMax,就可以初始化结果 res 了。然后进行循环,注意这里循环的条件不是队列不为空,而是当某个 list 的数字遍历完了就结束循环,因为范围要 cover 每个 list 至少一个数字。所以 while 循环条件即是队首数字所在的 list 的遍历位置小于该 list 的总个数,在循环中,取出队首数字所在的 list 序号t,然后将该 list 中下一个位置的数字和该 list 序号t组成 pair,加入队列中,然后用这个数字更新 curMax,同时 idx 中t对应的位置也自增1。现在来更新结果 res,如果结果 res 中两数之差大于 curMax 和队首数字之差,则更新结果 res,参见代码如下:
解法二:
class Solution {
public:
vector<int> smallestRange(vector<vector<int>>& nums) {
int curMax = INT_MIN, n = nums.size();
vector<int> idx(n, );
auto cmp = [](pair<int, int>& a, pair<int, int>& b) {return a.first > b.first;};
priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(cmp) > q(cmp);
for (int i = ; i < n; ++i) {
q.push({nums[i][], i});
idx[i] = ;
curMax = max(curMax, nums[i][]);
}
vector<int> res{q.top().first, curMax};
while (idx[q.top().second] < nums[q.top().second].size()) {
int t = q.top().second; q.pop();
q.push({nums[t][idx[t]], t});
curMax = max(curMax, nums[t][idx[t]]);
++idx[t];
if (res[] - res[] > curMax - q.top().first) {
res = {q.top().first, curMax};
}
}
return res;
}
};
Github 同步地址:
https://github.com/grandyang/leetcode/issues/632
类似题目:
参考资料:
https://leetcode.com/problems/smallest-range-covering-elements-from-k-lists/
LeetCode All in One 题目讲解汇总(持续更新中...)
[LeetCode] Smallest Range 最小的范围的更多相关文章
- LeetCode Smallest Range
数据范围是3500,3500也就是说n的平方是可以接受的.这里告诉你就是有序的,也就是在提醒你可能会是一个类似于二分的算法,所以的话其实基于这两个认识的话我们就可以利用一个枚举叫二分的算法来解决这道题 ...
- [LeetCode] 910. Smallest Range II 最小区间之二
Given an array A of integers, for each integer A[i] we need to choose either x = -K or x = K, and ad ...
- [LeetCode] 908. Smallest Range I 最小区间
Given an array A of integers, for each integer A[i] we may choose any x with -K <= x <= K, and ...
- [LeetCode] 632. Smallest Range Covering Elements from K Lists 覆盖K个列表元素的最小区间
You have k lists of sorted integers in ascending order. Find the smallest range that includes at lea ...
- [Swift]LeetCode632. 最小区间 | Smallest Range
You have k lists of sorted integers in ascending order. Find the smallest range that includes at lea ...
- 【LeetCode】632. Smallest Range 解题报告(Python)
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址: https://leetcode.com/problems/smallest ...
- [leetcode]632. Smallest Range最小范围
You have k lists of sorted integers in ascending order. Find the smallest range that includes at lea ...
- 一道题目- Find the smallest range that includes at least one number from each of the k lists
You have k lists of sorted integers. Find the smallest range that includes at least one number from ...
- LeetCode:长度最小的子数组【209】
LeetCode:长度最小的子数组[209] 题目描述 给定一个含有 n 个正整数的数组和一个正整数 s ,找出该数组中满足其和 ≥ s 的长度最小的连续子数组.如果不存在符合条件的连续子数组,返回 ...
随机推荐
- 数据库 用SQL语句操作数据
ACCP 马天鹏 2017/10/20 14:33:07用SQL语句操作数据. SQL的组成:(1)DML(Data Manipiation Language ,数据操作语言,)用来插入,修改和删除数 ...
- java基础笔记(6)----面向对象的三大特性
简介:面向对象的三大特性就是封装,继承,多态,是面向对象的核心. 封装 简介:封装是类的边界,可以对数据起到保护作用 特性:属性私有,提供公开的get/set方法 属性私有:private 数据类型 ...
- 分区表SQL调优/优化(Tuning)时容易“被欺骗”的场景之一
近几天没有用户找到,除了看看书,就是上网浏览点东西,好不惬意.可惜好景不长,正在享受悠闲惬意的日子时,一个用户的工作人员QQ找到我,说他们在统计一些数据,但一个SQL特别慢,或者说就从来没出过数据,我 ...
- hadoop集群简单搭建
分布式搭建 在ubuntu下创建hadoop用户组和用户 bigdata@master:~$sudo addgroup hadoop bigdata@master:~$sudo adduser --i ...
- c语音-第零次作业
1.你认为大学的学习生活.同学关系.师生应该是怎样? 我认为大学学习应该以自我学习为主,由以往的被动学习改为主动学习,探索新世界,除学习专业知识外对自身欠缺的地方也应该加以补足:同学之间要互相帮助,更 ...
- 20162318 实验四 Android程序设计
北京电子科技学院(BESTI) 实 验 报 告 课程:程序设计与数据结构 班级:1623班 姓名:张泰毓 指导老师:娄老师.王老师 实验日期:2017年5月26日 实验密级:非密级 实验器材:带Lin ...
- 部分和问题 nyoj
部分和问题 时间限制:1000 ms | 内存限制:65535 KB 难度:2 描述 给定整数a1.a2........an,判断是否可以从中选出若干数,使它们的和恰好为K. 输入 首先, ...
- Python爬虫之urllib模块2
Python爬虫之urllib模块2 本文来自网友投稿 作者:PG-55,一个待毕业待就业的二流大学生. 看了一下上一节的反馈,有些同学认为这个没什么意义,也有的同学觉得太简单,关于Beautiful ...
- Web Api 利用 cors 实现跨域
一.安装 cors 二.修改 Web.config <appSettings> <add key="cors:allowedMethods" value=&quo ...
- Postgres中postmaster代码解析(上)
之前我的一些文章都是在说Postgres的一些查询相关的代码.但是对于Postgres服务端是如何启动,后台进程是如何加载,服务端在哪里以及如何监听客户端的连接都没有一个清晰的逻辑.那么今天我来说说P ...