求k个数组包含每个数组至少一个元素的最小范围(待字闺中,备忘)
2013-10-23 15:47
274 查看
有k个有序的数组,请找到一个最小的数字范围。使得这k个有序数组中,每个数组都至少有一个数字在该范围中。
例如:
1: 4, 10, 15, 24, 26
2: 0, 9, 12, 20
3: 5, 18, 22, 30
所得最小范围为[20,24],其中,20在2中,22在3中,24在1中。
这是待字闺中的一道面试题,就个人经验来看一般有序数组的题目都会让人联想到有折半查找来解决,到有序数组为多个时,一般会联想到归并排序的思想,那么这道题就不例外。
以下引自待字闺中的分析:
那这个题目选择哪个方法继续尝试呢?那我们再分析一下要解决的问题。找到一个最小的范围,每一个有序数组中,都至少有一个元素在这个范围中。找到这样一个范围并不难,可是如何确定最小的范围呢?最终得到的最小的范围,至少包含三个元素,并且在所有数组整体的排序中,是相邻的。假设最小范围是[a, b, c],a < b < c。 c-a是最小的。并且,a,b,c来自不同的有序数组。还有一种情况是[a,b,d,c],a,b,c不是紧邻的,中间有一个d即: a< d < c。这时,d只能是来自b所在的数组,如下分析:
d来自a所在的数组,那么应有更短的范围c - d
d来自c所在的数组,那么应有更短的范围d - a
d来自b所在的数组,范围大小是不变的,就是无论是考虑d,还是考虑b。都没有影响。
从上面的分析,我们得出,只需要考虑在最终的排序中,考虑邻近的、并且来自不同有序数组的元素,作为备选的范围。那么该怎么样做到只考虑临近的、并且来自不同的有序数组的元素呢?这里就用到了归并排序的思想。以原题中的例子为例,假设有三个指针指,p1,p2,p3,分别指向三个数组的第一个元素:
结束是因为第二个数组已经没有元素可以再进行遍历了。最终得到最小的min_range_value为4,即为题目例子的答案。
上面这个方法,通过归并排序的思想,确保每次都是k个来自不同的数组的元素进行比较,得到最大值、最小值。就可以得到一个范围,包含了所有数组中的数字。
这个题的著名变种是从网页中产生包含所有查询词的最小的摘要。如果你 面过Google,你应该听说过这题。
个人的理解:
其实就是利用归并的思想,三个数组或更多个数组做归并排序,排在最小的元素向前移动,计算最大最小元素之间的间隔,这样当一个数组用尽的时候,记录的最小间隔即为所求。
例如:
1: 4, 10, 15, 24, 26
2: 0, 9, 12, 20
3: 5, 18, 22, 30
所得最小范围为[20,24],其中,20在2中,22在3中,24在1中。
这是待字闺中的一道面试题,就个人经验来看一般有序数组的题目都会让人联想到有折半查找来解决,到有序数组为多个时,一般会联想到归并排序的思想,那么这道题就不例外。
以下引自待字闺中的分析:
那这个题目选择哪个方法继续尝试呢?那我们再分析一下要解决的问题。找到一个最小的范围,每一个有序数组中,都至少有一个元素在这个范围中。找到这样一个范围并不难,可是如何确定最小的范围呢?最终得到的最小的范围,至少包含三个元素,并且在所有数组整体的排序中,是相邻的。假设最小范围是[a, b, c],a < b < c。 c-a是最小的。并且,a,b,c来自不同的有序数组。还有一种情况是[a,b,d,c],a,b,c不是紧邻的,中间有一个d即: a< d < c。这时,d只能是来自b所在的数组,如下分析:
d来自a所在的数组,那么应有更短的范围c - d
d来自c所在的数组,那么应有更短的范围d - a
d来自b所在的数组,范围大小是不变的,就是无论是考虑d,还是考虑b。都没有影响。
从上面的分析,我们得出,只需要考虑在最终的排序中,考虑邻近的、并且来自不同有序数组的元素,作为备选的范围。那么该怎么样做到只考虑临近的、并且来自不同的有序数组的元素呢?这里就用到了归并排序的思想。以原题中的例子为例,假设有三个指针指,p1,p2,p3,分别指向三个数组的第一个元素:
步骤 | 指针当前值 | 最大值 | 最小值 | min_range_value | 移动指针 |
1 | 4,0,5 | 5 | 0 | 5 | p2 |
2 | 4,9,5 | 9 | 4 | 5 | p1 |
3 | 10,9,5 | 10 | 5 | 5 | p3 |
4 | 10,9,18 | 18 | 9 | 9 | p2 |
5 | 10,12,18 | 18 | 10 | 8 | p1 |
6 | 15,12,18 | 18 | 12 | 6 | p2 |
7 | 15,20,18 | 20 | 15 | 5 | p1 |
8 | 24,20,18 | 24 | 18 | 6 | p3 |
9 | 24,20,22 | 24 | 20 | 4 | p2 |
end |
上面这个方法,通过归并排序的思想,确保每次都是k个来自不同的数组的元素进行比较,得到最大值、最小值。就可以得到一个范围,包含了所有数组中的数字。
这个题的著名变种是从网页中产生包含所有查询词的最小的摘要。如果你 面过Google,你应该听说过这题。
个人的理解:
其实就是利用归并的思想,三个数组或更多个数组做归并排序,排在最小的元素向前移动,计算最大最小元素之间的间隔,这样当一个数组用尽的时候,记录的最小间隔即为所求。
/************************************************************************* > File Name: mindiff.c > Author: desionwang > Mail: wdxin1322@qq.com > Created Time: Wed 23 Oct 2013 02:57:44 PM CST ************************************************************************/ #include<stdio.h> int mindiff(int a[], int size_a, int b[], int size_b, int c[], int size_c){ int i = 0, j = 0 ,k = 0; int minnum; int mindiff = 65535; if(a == NULL || b == NULL || c == NULL){ return -1; } if(size_a <= 0 || size_b <= 0 || size_c <= 0){ return -1; } int max, min, diff; int index; while(i < size_a && j < size_b && k < size_c){ printf("a:%d\tb:%d\tc:%d\n", a[i], b[j], c[k]); if(a[i] >= b[j]){ if(a[i] >= c[k]){ max = a[i]; }else{ max = c[k]; } if(b[j] <= c[k]){ min = b[j]; index = j; j++; }else{ min = c[k]; index = k; k++; } }else{ if(b[j] >= c[k]){ max = b[j]; }else{ max = c[k]; } if(a[i] <= c[k]){ min = a[i]; index = k; i++; }else{ min = c[k]; index = i; k++; } } printf("max:%d\tmin:%d\n", max, min); //printf("a:%d\tb:%d\tc:%d\n", a[i], b[j], c[k]); diff = max - min; if(diff < mindiff){ mindiff = diff; } } //printf("a:%d\tb:%d\tc:%d\n", a[i], b[j--], c[k]); printf("mindiff:%d\n", mindiff); return mindiff; } int main(){ int a[5] = {4, 10, 15, 24, 26}; int b[] = {0, 9, 12, 20}; int c[] = {5, 18, 22, 30}; mindiff(a, 5, b, 4, c , 4); }
相关文章推荐
- 转:最小区间:k个有序的数组,找到最小区间使k个数组中每个数组至少有一个数在区间中
- 定义一个int型的一维数组,包含10个元素,分别赋一些随机整数,然后求出所有元素的最大值,最小值,平均值,和值,并输出出来。
- List的All方法使用问题:我用List1的All方法来确保List1的所有每个数组元素中是否包含Arr1中的任意元素,这个部分很难实现。 因为,没有一个数组中是否包含另一个数组中的任意元素这个功能
- 在一个数组中查找最大的K个元素或者最小的K个元素
- 给定一个长度为N的数组,其中每个元素的取值范围都是1到N。判断数组中是否有重复的数字。(原数组不必保留)
- Java编程:定义一个int型的一维数组,包含10个元素,分别赋一些随机整数,然后求出所有元素的最大值,最小值,平均值,和值,并输出出来。
- 数组中的数分为两组,让给出一个算法,使得两个组的和的差的绝对值最小,数组中的数的取值范围是0<x<100,元素个数也是大于0, 小于100 。
- 设一个长度为10的整型数组, 0)要求每个元素的值通过scanf输入,输入完成后, 1)请顺序输出这些整数, 2)请倒序输出这些整数, 3)输出这些数中的最大值, 4)输出这些数中的最小值
- 数组中的数分为两组,让给出一个算法,使得两个组的和的差的绝对值最小,数组中的数的取值范围是0<x<100,元素个数也是大于0, 小于100 。
- 最小区间使得至少包含每组元素中的一个
- 谷歌面试题--一个大小为n的数组,里面的数都属于范围[0, n-1],有不确定的重复元素,找到至少一个重复元素,要求O(1)空间和O(n)时间
- 新浪微博 陈利人 面试题 给定k个数组,每个数组有k个整数。每个数组中选取一个整数,一共k个整数,取其和,一共可以得到k^k个和。给出方法,求得这k^k个和中,最小的k个。
- 【1】 设一个长度为10的整型数组,  0)要求每个元素的值通过scanf输入,输入完成后,  1)请顺序输出这些整数,  2)请倒序输出这些整数,  3)输出这些数中的最大值,最小值
- 给定一个非负整数数组,最初定位在数组的第一个索引处。组中的每个元素表示您在该位置的最大跳跃长度。求最小跳数
- 定义一个int型的一维数组,包含40个元素,用来存储每个学员的成绩,循环产生40个 0~100之间的随机整数,将它们存储到一维数组中,
- 一个长度为N的整形数组,数组中每个元素的取值范围是[0,N-1],写一个算法判断数组中是否存在重复的数字
- 给定n个数组编号1~n,给定一个范围,使得这个范围包含第k个数组至少ak个数的算法
- 问题: 一个数组长度为n, 求出其最小的k个元素并从小到大输出
- 算法导论9.3-8-设X[1..n]和Y[1..n]为两个数组,每个都包含n个已排好序的数,给出一个求数组X和数组Y中所有2n个元素的中位数
- range() 函数创建并返回一个包含指定范围的元素的数组