zoukankan      html  css  js  c++  java
  • Leetcode 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. 给定的列表可能包含重复元素,所以在这里升序表示 >= 。
    2. 1 <= k <= 3500
    3. -105 <= 元素的值 <= 105
    4. 对于使用Java的用户,请注意传入类型已修改为List<List<Integer>>。重置代码模板后可以看到这项改动。

    思路

    这个题来自打车公司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的尽头)。

     

     1 class Solution {
     2     public int[] smallestRange(List<List<Integer>> nums) {
     3         int curMin = 0;
     4         int curMax = Integer.MAX_VALUE;
     5         int[] pointerIndex = new int[nums.size()];// maintain一个数组来记录每层list当前的pointer的index
     6         boolean flag = true;  // flag辅助判断是否有某个list走到了末尾
     7 
     8         for (int i = 0; i < nums.size() && flag; i++) { // 外层循环遍历list
     9             for (int j = 0; j < nums.get(i).size() && flag; j++) { // 内层循环遍历某个list的第 j 个元素
    10                 int minValueLevel = 0;
    11                 int maxValueLevel = 0;
    12                 for (int k = 0; k < nums.size(); k++) {
    13                     if (nums.get(minValueLevel).get(pointerIndex[minValueLevel]) > nums.get(k).get(pointerIndex[k])) {
    14                         minValueLevel = k;
    15                     }
    16                     if (nums.get(maxValueLevel).get(pointerIndex[maxValueLevel]) < nums.get(k).get(pointerIndex[k])) {
    17                         maxValueLevel = k;
    18                     }
    19                 }
    20                 // 是否更新smallest range
    21                 if (nums.get(maxValueLevel).get(pointerIndex[maxValueLevel]) - nums.get(minValueLevel).get(pointerIndex[minValueLevel]) < curMax - curMin) {
    22                     curMin = nums.get(minValueLevel).get(pointerIndex[minValueLevel]);
    23                     curMax = nums.get(maxValueLevel).get(pointerIndex[maxValueLevel]);
    24                 }
    25                 // 移动当前找到的最小值对应的pointer
    26                 pointerIndex[minValueLevel]++;
    27                 // flag辅助判断是否有某个list走到了末尾
    28                 if (pointerIndex[minValueLevel] == nums.get(minValueLevel).size()) {
    29                     flag = false;
    30                     break;
    31                 }
    32 
    33             }
    34         }
    35         return new int[]{curMin, curMax};
    36     }
    37 }

     

     

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

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

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

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

    能够在时间上进行优化。

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

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

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

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

    能够在时间上进行优化。

     

     1 import java.util.List;
     2 import java.util.PriorityQueue;
     3 
     4 class Solution {
     5     public int[] smallestRange(List<List<Integer>> nums) {
     6         int curMin = 0;
     7         int curMax = Integer.MAX_VALUE;
     8         int max = Integer.MIN_VALUE;
     9         int[] pointerIndex = new int[nums.size()];
    10         boolean flag = true;
    11         PriorityQueue<Integer> queue = new PriorityQueue<Integer>((i, j) -> nums.get(i).get(pointerIndex[i]) - nums.get(j).get(pointerIndex[j]));
    12         for (int i = 0; i < nums.size(); i++) {
    13             queue.add(i);
    14             max = Math.max(max, nums.get(i).get(0));
    15         }
    16         for (int i = 0; i < nums.size() && flag; i++) {
    17             for (int j = 0; j < nums.get(i).size() && flag; j++) {
    18                 int minValueLevel = queue.poll();
    19                 // 是否更新smallest range
    20                 if (max - nums.get(minValueLevel).get(pointerIndex[minValueLevel]) < curMax - curMin) {
    21                     curMin = nums.get(minValueLevel).get(pointerIndex[minValueLevel]);
    22                     curMax = max;
    23                 }
    24                 // 移动当前找到的最小值对应的pointer
    25                 pointerIndex[minValueLevel]++;
    26                 // flag辅助判断是否有某个list走到了末尾
    27                 if (pointerIndex[minValueLevel] == nums.get(minValueLevel).size()) {
    28                     flag = false;
    29                     break;
    30                 }
    31                 queue.offer(minValueLevel);
    32                 max = Math.max(max, nums.get(minValueLevel).get(pointerIndex[minValueLevel]));
    33 
    34             }
    35         }
    36         return new int[]{curMin, curMax};
    37     }
    38 }

     

     

  • 相关阅读:
    OpenEuler 中C与汇编的混合编程
    实验四 Web服务器2
    实验四 Web服务器1
    OpenEuler中C语言中的函数调用测试
    第14章学习笔记(20191213兰毅达)
    第13章学习笔记(20191213兰毅达)
    第12章学习笔记(20191213兰毅达)
    冲刺day5
    Oracle中Sequence使用
    Oracle中dual表的用途
  • 原文地址:https://www.cnblogs.com/kexinxin/p/10381442.html
Copyright © 2011-2022 走看看