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

题意:

给定一些sorted array, 求一个最小范围,使得该范围内至少包含每个数组中的一个数字。

思路:

这个题来自打车公司lyft,现实意义是模拟该app在很多user登陆的登陆时间,narrow一个范围,这样就可以在user登陆时间最频繁的范围里投放广告或者做些其他的商业行为。

two pointer的思路。

三个指针zero、first、second同时从每个list的首元素出发。用pointerIndex来维护一个数组记录每个list当前指针的index。

比较三个指针对应的元素大小。记录比较后的curMin, curMax,更新smallest range。

移动curMin对应的指针,比较三个指针对应的元素大小。记录比较后的curMin, curMax,更新smallest range。 更新pointerIndex。

直至curMin对应的指针无法移动为止(即curMin走到了某个list的尽头)。

[4,10,15,24,26]
^
zero [0,9,12,20]
^
first [5,18,22,30]
^
second

curMin        curMax         range          pointerIndex

zero|first|second

init                                                    0                  5                 5              0  |  0  |  0

curMin对应的指针first++                       4                  9                 5              0  |  1  |  0

curMin对应的指针zero++                       5                 10                5               1  |  1  |  0

curMin对应的指针second++                   9                 18                9               1  |  1  |  1

curMin对应的指针first++                       10                18                8               1  |  2  |  1

curMin对应的指针zero++                      12                 18               6                2  |  2  |  1

curMin对应的指针first++                       15                20               5                2  |  3  |  1

curMin对应的指针zero++                      18                24                6                3  |  3  |  1

curMin对应的指针second++                 20                 24                4                3  |  3  |  2

代码一:

  public int[] smallestRange2(List<List<Integer>> nums) {
int curMin = 0;
int curMax = Integer.MAX_VALUE;
int[] pointerIndex = new int[nums.size()];// maintain一个数组来记录每层list当前的pointer的index
boolean flag = true; // flag辅助判断是否有某个list走到了末尾 for (int i = 0; i < nums.size() && flag; i++) { // 外层循环遍历list
for (int j = 0; j < nums.get(i).size() && flag; j++) { // 内层循环遍历某个list的第 j 个元素
int minValueLevel = 0;
int maxValueLevel = 0;
for (int k = 0; k < nums.size(); k++) {
if (nums.get(minValueLevel).get(pointerIndex[minValueLevel]) > nums.get(k).get(pointerIndex[k])) {
minValueLevel = k;
}
if (nums.get(maxValueLevel).get(pointerIndex[maxValueLevel]) < nums.get(k).get(pointerIndex[k])) {
maxValueLevel = k;
}
}
// 是否更新smallest range
if (nums.get(maxValueLevel).get(pointerIndex[maxValueLevel]) - nums.get(minValueLevel).get(pointerIndex[minValueLevel]) < curMax - curMin) {
curMin = nums.get(minValueLevel).get(pointerIndex[minValueLevel]);
curMax = nums.get(maxValueLevel).get(pointerIndex[maxValueLevel]);
}
// 移动当前找到的最小值对应的pointer
pointerIndex[minValueLevel]++;
// flag辅助判断是否有某个list走到了末尾
if (pointerIndex[minValueLevel] == nums.get(minValueLevel).size()) {
flag = false;
break;
} }
}
return new int[]{curMin, curMax};
}

这个代码在oj上显示time limit exceeded

因为每次都要比较三个指针对应元素的curMin和curMax,  我们可以用一个PriorityQueue来优化。

PriorityQueue里面存放当前三个指针对应的元素。

PriorityQueue 删除极值的时间复杂度是 O(logN), 查找极值的时间复杂度是 O(1)

能够在时间上进行优化。

代码二:

   public int[] smallestRange(List<List<Integer>> nums) {
int curMin = 0;
int curMax = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;
int[] pointerIndex = new int[nums.size()];
boolean flag = true;
PriorityQueue<Integer> queue = new PriorityQueue<Integer>((i, j) -> nums.get(i).get(pointerIndex[i]) - nums.get(j).get(pointerIndex[j]));
for (int i = 0; i < nums.size(); i++) {
queue.add(i);
max = Math.max(max, nums.get(i).get(0));
}
for (int i = 0; i < nums.size() && flag; i++) {
for (int j = 0; j < nums.get(i).size() && flag; j++) {
int minValueLevel = queue.poll();
// 是否更新smallest range
if (max - nums.get(minValueLevel).get(pointerIndex[minValueLevel]) < curMax - curMin) {
curMin = nums.get(minValueLevel).get(pointerIndex[minValueLevel]);
curMax = max;
}
// 移动当前找到的最小值对应的pointer
pointerIndex[minValueLevel]++;
// flag辅助判断是否有某个list走到了末尾
if (pointerIndex[minValueLevel] == nums.get(minValueLevel).size()) {
flag = false;
break;
}
queue.offer(minValueLevel);
max = Math.max(max, nums.get(minValueLevel).get(pointerIndex[minValueLevel])); }
}
return new int[]{curMin, curMax};
}

[leetcode]632. Smallest Range最小范围的更多相关文章

  1. [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 ...

  2. 【LeetCode】632. Smallest Range 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 题目地址: https://leetcode.com/problems/smallest ...

  3. [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 ...

  4. [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 ...

  5. 632. Smallest Range(priority_queue)

    You have k lists of sorted integers in ascending order. Find the smallest range that includes at lea ...

  6. 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 ...

  7. LeetCode 910. Smallest Range II

    很有意思的一道数学推理题目, 剪枝以后解法也很简洁.初看貌似需要把每个数跟其他数作比较.但排序以后可以发现情况大大简化:对于任一对元素a[i] < a[j], a[i] - k和a[j] + k ...

  8. [LeetCode] Smallest Range 最小的范围

    You have k lists of sorted integers in ascending order. Find the smallest range that includes at lea ...

  9. [Swift]LeetCode632. 最小区间 | Smallest Range

    You have k lists of sorted integers in ascending order. Find the smallest range that includes at lea ...

随机推荐

  1. python中__name__的使用

    这几天开始学习Python,遇到一些问题,也解决了一些问题. 其中if __name__ == '__main__':这句估计很多和我一样的初学者都是不求甚解.这里作一下解释: 1:__name__是 ...

  2. 安装phoenix时,执行命令./sqlline.py hostname1,hostname2.hostname3..... 时报错 ImportError: No module named argparse

    问题描述: 怎么解决呢: 网上看了好多方法,但是本屌丝表示看不懂啊,没理解人家的博客的博大精深,好吧我们回到正题!! 先切换到root用户下安装这个东西  yum  install  python-a ...

  3. java字符串分解 StringTokenizer用法

    Java中substring方法可以分解字符串,返回的是原字符串的一个子字符串.如果要讲一个字符串分解为一个一个的单词或者标记,StringTokenizer可以帮你. 先看个例子: 1 public ...

  4. kubernetes学习 做持久化存储

    本节演示如何为 MySQL 数据库提供持久化存储,步骤: 1.创建 PV 和 PVC 2.部署 MySQL 3.向 MySQL 添加数据 4.模拟节点宕机故障,Kubernetes 将 MySQL 自 ...

  5. node多进程

    内容: 1.多进程与多线程 2.node中多进程相关模块的使用 1.多进程与多线程 多线程:性能高:复杂.考验程序员 多进程:性能略低:简单.对程序员要求低 Node.js中默认:单进程.单线程,但是 ...

  6. Rust笔记

    前言: 学了有段时间了,现在同步到博客园. 正文: Rust语言介绍 l Rust由js之父开发的新型语言,打破了传统的难以接触底层的局面.这是个有C++开发的语言.拥有C的血统 l Rust必须严格 ...

  7. 17.scrapy框架简例使用

    目标:创建scrapy项目 创建一个spider来抓取站点和处理数据 通过命令行将抓取内容导出 1.创建项目 scrapy startproject tutorial 2.创建spider cd tu ...

  8. (12/24) css进阶:sass文件的打包和分离

    1.安装sass打包的loader 这里需要 在项目目录下用npm安装两个包.node-sass和sass-loader,(也可以使用cnpm安装) 因为sass-loader依赖于node-sass ...

  9. 使用JSP页面生成PDF报表

    转自:http://developer.51cto.com/art/200907/134261.htm 1.iText简介 iText是一个开放源码的Java类库,可以用来方便地生成PDF文件.大家通 ...

  10. as3与php交互

    (1)直接读取 php: <? $state="开始接收"; $var1="收到"; echo "state=".$state.&qu ...