zoukankan      html  css  js  c++  java
  • 转:最小区间:k个有序的数组,找到最小区间使k个数组中每个数组至少有一个数在区间中

    转:http://www.itmian4.com/thread-6504-1-1.html

    最小区间原题

    k个有序的数组,找到最小的区间范围使得这k个数组中,每个数组至少有一个数字在这个区间范围内。比如:

    • 数组1:[4, 10, 15, 24, 26]
    • 数组2:[0, 9, 12, 20]
    • 数组3:[5, 18, 22, 30]

    最小的区间是[20, 24],这个区间包含了数组1中的24,数组2中的20,数组3中的22

    • 思考时间~~~

    分析

    该题看起来还算比较简单,大家通常都会想到:为每一个数组设置一个遍历变量,选择最小值的数组,继续往后移动一位。由于是有k个数组,数组的数量有可能很多,所以如何去选择和替换最小的值,我们就会想到一个数据结构最小堆来维护最小的值。

    解答方法:
    初始化大小为k的最小堆,k个数字是每个数组中的最小值,设置变量maxValue记录k个数字中最大值,删除堆顶元素,将原堆顶元素对应的数组中下一个值加入到堆中,调整堆,并且记录当前区间范围(maxValue - minValue),重复执行直到某个数组所有值都被删除。

    比如.
    List 1: [4, 10, 15, 24, 26]
    List 2: [0, 9, 12, 20]
    List 3: [5, 18, 22, 30]

    最小堆大小为3. 从三个数组中取最小值
    Heap [0, 4, 5] maxValue 5
    Range - 6

    删除0 ,加入9
    Heap [4, 9, 5] maxValue 9
    Range - 6

    删除4 ,加入10
    Heap [5, 9, 10] maxValue 10
    Range - 6

    重复执行,最终得到结果

    代码如下:

     

     1 struct pn
     2 {
     3     int n; /* belong to which array */
     4     int d; /* the data value */
     5     pn(int _n, int _d) { n = _n; d = _d; }
     6     pn(const pn& _pn) { n = _pn.n; d = _pn.d; }
     7 };
     8 
     9 inline void swap(pn& a, pn& b) { pn c = a; a = b; b = c; }
    10 
    11 void adjust(int n, pn a[])
    12 {
    13     int i = 0, max = 0;
    14     int l = 0, r = 0;
    15     for(i = n / 2; i >= 0; i--)
    16     {
    17         max = i;
    18         l = 2 * i + 1;
    19         r = 2 * i + 2;
    20         if(l < n && a[l].d > a[max].d) { max = l; }
    21         if(r < n && a[r].d > a[max].d) { max = r; }
    22         if(max != i) { swap(a[max], a[i]); }
    23     }
    24 }
    25 
    26 void heapsort(int n, pn a[])
    27 {
    28     int i = 0;
    29     adjust(n, a);
    30     for(i = n - 1; i > 0; i--)
    31     {
    32         swap(a[0], a[i]);
    33         adjust(i, a);
    34     }
    35 }
    36 
    37 int main()
    38 {
    39     int i = 0, j = 0;
    40     const int m = 3;
    41     const int n = 5;
    42     int ms = 0, me = 0;
    43     int ts = 0, te = 0;
    44     int a[m][n] = { {4, 10, 15, 24, 26}, {0, 9, 12, 20, 35}, {5, 18, 22, 30, 50} };
    45     int cur[m] = {1, 1, 1}; /* record the current positions of each array which haven't been used */
    46     pn heap[m] = {pn(0, a[0][0]), pn(1, a[1][0]), pn(2, a[2][0])};
    47 
    48     heapsort(m, heap);
    49     ms = heap[0].d;
    50     me = heap[m - 1].d;
    51     while(true)
    52     {
    53         heapsort(m, heap);
    54         ts = heap[0].d;
    55         te = heap[m - 1].d;
    56         /* if the current range is smaller than the minimum range */
    57         if(te - ts < me - ms) { ms = ts; me = te; }
    58 
    59         /* if the sub-array which the smallest element comes from hasn't to the end */
    60         if(cur[heap[0].n] != n)
    61         {
    62             heap[0].d = a[heap[0].n][cur[heap[0].n]];
    63             cur[heap[0].n] += 1;
    64         }
    65         else
    66         {
    67             break;
    68         }
    69     }
    70     cout << ms << endl;
    71     cout << me << endl;
    72     return 0;
    73 }

     

    以下是自己的思路:

    1 每个数组取最后一个值,从这些值当中选出最小值,记为min。

    2 遍历每一个数组(min对应的数组返回-1),从中找到第一个大于min的值,再从这些值当中选出最大值。

    3 最小区间即为[min, max]。

    不知道有没有漏洞?实现以后补上。

     

  • 相关阅读:
    Uva455
    PAT乙级1059
    PAT乙级1092
    PAT乙级1076
    PAT乙级1065
    PAT乙级1049
    Uva1586
    《肇造区夏》读后感 读书笔记
    《老鼠虱子和历史》读后感 读书笔记
    《胡适口述自传》读后感 读书笔记
  • 原文地址:https://www.cnblogs.com/kira2will/p/4019588.html
Copyright © 2011-2022 走看看