转:最小区间: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]。

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

时间: 2024-10-07 18:11:00

转:最小区间:k个有序的数组,找到最小区间使k个数组中每个数组至少有一个数在区间中的相关文章

【java】解析java中的数组

目录结构: contents structure [-] 一维数组 1,什么是一维数组 2,声明一维数组的三种方式 二维数组 1,什么是二维数组 2,声明二维数组的3种方式 3,二维数组的遍历示例 数组在内存中的空间分配情况 各种数据类型在声明完毕后的默认初始值 解析数组中length属性 java中的数组是对象吗 创建数组对象的模板在哪里 java数组中.lenght属性的来源 参考文章 1,一维数组 1.1 什么是一维数组 一维数组就是在内存连续分配的一段存储空间. 1.2 声明一维数组的三

如何在JSTL中获取数组或者list对象的索引值(index)

<c:forEach items="${productList}" var="products" varStatus="status"> 产品序号:${status.count} 产品名称:${products.name} </c:forEach> 上面代码中的varStatus是关键,${status.count}即是我们要的数组的索引值. 如何在JSTL中获取数组或者list对象的索引值(index)

合并k个有序数组

给定K个有序数组,每个数组有n个元素,想把这些数组合并成一个有序数组 可以利用最小堆完成,时间复杂度是O(nklogk),具体过程如下: 创建一个大小为n*k的数组保存最后的结果创建一个大小为k的最小堆,堆中元素为k个数组中的每个数组的第一个元素重复下列步骤n*k次:每次从堆中取出最小元素(堆顶元素),并将其存入输出数组中用堆顶元素所在数组的下一元素将堆顶元素替换掉,如果数组中元素被取光了,将堆顶元素替换为无穷大.每次替换堆顶元素后,重新调整堆初始化最小堆的时间复杂度O(k),总共有kn次循环,

两个有序数组的中位数(第k大的数)

问题:两个已经排好序的数组,找出两个数组合并后的中位数(如果两个数组的元素数目是偶数,返回上中位数). 感觉这种题目挺难的,尤其是将算法完全写对.因为当初自己微软面试的时候遇到了,但是没有想出来思路.看网上写了一堆解法,但是将思路说得非常清楚的少之又少. 有两种思路,一个是算法导论里面的,一个是求解k大元素.建议使用下面第二种思路,代码少不容易出错. 下面的内容摘自:https://blog.csdn.net/hackbuteer1/article/details/7584838 求解中位数,算

有序数组寻找中位数以及寻找K大元素

问题描述: 两个排序的数组A和B分别含有m和n个数,找到两个排序数组的中位数,要求时间复杂度应为O(log (m+n)).转化成找到两个数组的第K大数字进行解决 解题方法: 对于一个长度为n的已排序数列a,若n为奇数,中位数为a[n / 2 + 1] , 若n为偶数,则中位数(a[n / 2] + a[n / 2 + 1]) / 2如果我们可以在两个数列中求出第K小的元素,便可以解决该问题不妨设数列A元素个数为n,数列B元素个数为m,各自升序排序,求第k小元素取A[k / 2] B[k / 2]

经典算法——合并K个有序链表

一.题目要求: 将K个有序链表合并为一个有序链表 二.实现方法: 方法一:利用最小堆方法 用一个大小为K的最小堆(用优先队列+自定义降序实现)(优先队列就是大顶堆,队头元素最大,自定义为降序后,就变成小顶堆,队头元素最小),先把K个链表的头结点放入堆中,每次取堆顶元素,然后将堆顶元素所在链表的下一个结点加入堆中. 整体测试代码: #include <vector> #include <iostream> #include<queue> #include<set&g

合并k个有序链表

题目: 合并k个有序链表,并将结果用一个有序链表输出 例如:输入: [   1->4->5,   1->3->4,   2->6 ] 输出: 1->1->2->3->4->4->5->6 思路: 假设k个链表的总元素数目为n.首先想到两两合并列表,在序列1和2合并,3和4合并,依次类推.直到合并的只剩一个链表.这种操作的时间复杂度为O(nlog(k)),空间复杂度为O(1).python代码如下: class Solution(obj

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

[算法]打印N个数组的整体最大Top K

题目: 有N个长度不一的数组,所有的数组都是有序的,请从大到小打印这N个数组整体最大的前K个数. 例如: 输入含有N行元素的二维数组代表N个一维数组. 219,405,538,845,971 148,558 52,99,348,691 再输入整数K=5,则打印: Top 5:971,845,961,558,538. 要求: 1.如果所有数组的元素个数小于K,则从小到大打印所有的数. 2.时间复杂度为O(KlogN). 解答: 利用堆结构和堆排序完成. import java.util.Array