1. 程式人生 > 實用技巧 >[LeetCode] 632. Smallest Range Covering Elements from K Lists

[LeetCode] 632. Smallest Range Covering Elements from K Lists

You haveklists of sorted integers in ascending order. Find thesmallestrange that includes at least one number from each of theklists.

We define the range [a,b] is smaller than range [c,d] ifb-a < d-cora < cifb-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.

最小區間。題意是給一個list of list,sublist裡面都是整數,且每個sublist都是有序的。請返回一個最小區間,使得input裡的每個sublist至少有一個元素在這個最小區間裡。

這道題我是用priority queue做的。這道題其實還有滑動視窗的做法,我之後再補充吧。

我們照著這個例子講一下思路,

Input: [[4,10,15,24,26], [0,9,12,20], [5,18,22,30]]

因為每個sublist都是有序的,所以可以先把每個sublist的第一個元素加入一個以priority queue建立的最小堆,這樣,最小的元素始終在堆頂。在把所有sublist的第一個元素加入pq之後,同時也得到了一個第一個區間[0, 5]。

接著開始往後遍歷,因為第一個區間是[0, 5],如果想試著縮小這個區間,那麼要不然就是提高下限要不然就是提高上限。因為所有的sublist都是遞增的所以只能試著提高下限。因為0又是堆頂元素,所以去掉0,加入0所在的sublist之後的那個數字9。此時pq裡是[4, 5, 9],同時最大元素是9,最小元素是4,新的區間是[4, 9],區間並沒有比之前小,不更新。

第三輪,此時因為堆頂元素是4,所以彈出4,加入4之後的那個元素10,此時pq裡面是[5, 9, 10],新的區間是[5, 10],區間並沒有比之前小,不更新。

第四輪,堆頂元素是5,彈出5,加入5之後的那個元素18,此時pq裡面是[9, 10, 18],區間並沒有比之前小,不更新。

第五輪,堆頂元素9,彈出9,加入9之後的那個元素12,此時pq裡面是[10, 12, 18],區間並沒有比之前小,不更新。

第六輪,堆頂元素10,彈出10,加入10之後的那個元素15,此時pq裡面是[12, 15, 18],區間並沒有比之前小,不更新。

……

照著這個方式去遍歷,把所有sublist裡面的數字都通過pq過濾一遍,最後會得到最小的區間[20, 24]。

時間O(nlogk)

空間O(k)

Java實現

 1 class Solution {
 2     public int[] smallestRange(List<List<Integer>> nums) {
 3         // corner case
 4         if (nums == null || nums.size() == 0) {
 5             return new int[0];
 6         }
 7 
 8         // normal case
 9         int[] res = new int[2];
10         PriorityQueue<int[]> minHeap = new PriorityQueue<>((a, b) -> a[0] - b[0]);
11         int max = Integer.MIN_VALUE;
12         int minLen = Integer.MAX_VALUE;
13         int n = nums.size();
14         for (int i = 0; i < n; i++) {
15             int num = nums.get(i).get(0);
16             minHeap.add(new int[] { num, i, 0 });
17             max = Math.max(max, num);
18         }
19 
20         while (minHeap.size() == n) {
21             int[] cur = minHeap.poll();
22             if (max - cur[0] < minLen) {
23                 minLen = max - cur[0];
24                 res[0] = cur[0];
25                 res[1] = max;
26             }
27             if (cur[2] < nums.get(cur[1]).size() - 1) {
28                 int num = nums.get(cur[1]).get(cur[2] + 1);
29                 minHeap.add(new int[] { num, cur[1], cur[2] + 1 });
30                 max = Math.max(max, num);
31             }
32         }
33         return res;
34     }
35 }

LeetCode 題目總結