求两个已序数组的中位数
来源:互联网 发布:五子棋游戏c语言代码 编辑:程序博客网 时间:2024/04/29 10:35
本文转自:http://dsqiu.iteye.com/blog/1715280
题目:
已知两个数组x[]与y[],各有n个元素,并且也已经以从小到大的顺序排好,编写一 个程序,用少于n次比较找出x[]与y[]合并后的中位数。
说明:
因为x[]与y[]都已经排好,而且各有n个元素,因此一般最自然的想法就是把x[]与 y[]做合并的工作,一直合并到得出第a个元素时,这就是中位数了,这一共会用n次比较。 注意,为方便起见,把中位数定成在中间的两个及其中之一,这是个方便的定义,因为x[] 与y[]合起来有2n个元素,因此真正的中位数的定义应该是第n与第n+1个元素的平均数; 所以为了方便,只要求找出第n个或第n+1个元素即可。
上面提到的,用合并的方法会用到与II成正比的比较次数,并不是所期望的做法,所希望的,是要比n少很多的做法。可能会想到的改善是:因为x[]与y[]是排好的,可以用 x[]的中间元素,例如x[mid],通过二分查找法找出它在y[]数组中的位置,例如:
y[i] < x [mid] < y [i + 1]
所以在合并起来之后,x[mid]前面的元素就有mid+i+1个,如果这个值大于n,那么中位数就必定在这mid+i+1个元素内,因此x[mid+l]〜x[n-1],y[i+1]〜y[n-1]都可以去掉,接着在x[0]〜x[mid],y[0]〜y[i]之间找中位数就行了。但若mid+i+1比n小,在合并起来后中 位数在元素多的那一半,所以把x[0]〜x[mid],y[0]〜y[i]去掉,而在x[mid+1]〜x[n-1],y[i+1]〜x[n-1]之间找中位数。反复这个过程,就不难找出中位数了。需要多少次比较呢?大约与 (log2n)^2成正比,道理为何请读者自己证明。
事实上,问题还可以做得更好,而且也不必那么复杂,在与log2n成正比的比较次数
之下就可以找出中位数的。
解答:
其实在问题说明中的(log2n)2方法已经差不多可以说是涉及到重点所在了,它之所以 到不了 log2ii的境界,是因为每次所去掉的、不可能包含了中位数的元素个数不够多。为了要去掉足够多的、不适合的元素,要把那个办法动一点手脚才行。想法是,一次要去掉 将近一半的元素(就像是二分搜寻法一样),大约log2n次之后,就可以得到结果了。
首先,拿x[mid_x]与y[mid_y]这两个在x[]与y[]中央的元素比较。如果x[mid_x]比 y[mid_y]小,那么在合并后的结果中x[mid_x]就排在y[mid_y]前面,而且中位数一定在这 两者之间。原因是在x[]中,在x[mid_x]之前有n/2个元素,同理,y[]中在y[mid_y]之前也有n/2个元素,所以合并后至少会包含了所有小于等于x[mid一x]与y[mid_y]的元素,这样就有了 n个。但因为x[mid_x]小于等于y[mid_y+1],所以x[]中比x[mid_x]大的部分也有 若干元素落在y[mid_j]的前面,所以合并后在y[mid_j]之前就有不止n个元素。换句话说, 中位数一定在y[mid_y]之前。正因为如此,在y[]中比y[mid_j]大的元素中就不可能含有中位数了,所以y[mid_y+1]〜y[n-1]的元素就可以去掉,只留下y[0]〜y[mid_y],这样y[]中 就被去掉了差不多一半的元素。
再看x[mid_x]。在x[]中比它小的不足n/2个元素,可以把x[]中x[0]~x[mid_x-1]的元素去掉,因此x[]几乎去掉了一半的元素。
代码实现:
代码实现:
void sort(int [], int);int median(int x[], int y[], int n){ int first_X = 0; /* lower element of x[] */ int first_Y = 0; /* lower element of y[] */ int last_X = n-1; /* higher element of x[] */ int last_Y = n-1; /* higher element of y[] */ int count = 0; /* # of smaller items elim. */ int mid_X, mid_Y; /* middle element pointers */ int number; /* # of elements left */ int z[4]; /* working array */ while ((last_X - first_X > 1) || (last_Y - first_Y > 1)) { mid_X = (first_X + last_X)/2; /* get mid ptrs */ mid_Y = (first_Y + last_Y)/2; if (x[mid_X] <= y[mid_Y]) { count += (mid_X - first_X); /* inc. count*/ first_X = mid_X; /* elim. lower half x[] */ last_Y = mid_Y; /* elim. higher half x[] */ } else { count += (mid_Y - first_Y); first_Y = mid_Y; /* elim. lower half y[] */ last_X = mid_X; /* elim. higher half x[] */ } } for (number = 0; first_X <= last_X; first_X++) z[number++] = x[first_X]; /* collect remainder */ for ( ; first_Y <= last_Y; first_Y++) z[number++] = y[first_Y]; sort(z, number); /* sort them */ return z[n-count-1]; /* pick up appropriate item */}/* ------------------------------------------------------ *//* FUNCTION sort : *//* Special routine to sort small arrays with 2, 3 and *//* 4 elements. *//* ------------------------------------------------------ */#define SWAP(x, y) { temp = x; x = y; y = temp; }void sort(int z[], int n){ int temp; switch (n) { case 4 : if (z[0] >= z[3]) SWAP(z[0], z[3]); if (z[1] >= z[3]) SWAP(z[1], z[3]); if (z[2] >= z[3]) SWAP(z[2], z[3]); case 3 : if (z[0] >= z[2]) SWAP(z[0], z[2]); if (z[1] >= z[2]) SWAP(z[1], z[2]); case 2 : if (z[0] >= z[1]) SWAP(z[0], z[1]); }}/* ------------------------------------------------------ */#include <stdio.h>void main(void){ int x[] = { 1, 3, 6, 7, 8, 9, 10}; int y[] = { 2, 4, 5, 11, 12, 13, 14}; int n = sizeof(x)/sizeof(int); int i; printf("\nMedian of Two Sorted Arrays"); printf("\n==========================="); printf("\n\nArray #1 Array #2"); printf( "\n-------- --------"); for (i = 0; i < n; i++) printf("\n%6d%13d", x[i], y[i]); printf("\n\nMedian is %d", median(x, y, n));}
- 求两个已序数组的中位数
- 已知两个同规模的已序数组,求其中位数
- leetCode_发现两排好序数组的中位数
- 求两个数组的中位数
- 求两个大小为n的已排序数组的中位数
- 求两个已排序(升序)等长的整数数组所有元素的中位数
- 【算法】找出两个已序数组,是否含有相同的数字
- GEEK编程练习— —两个已序数组的中值
- 求两个等长已排序数组的中位数(算法导论习题9.3-8)
- 求两个相同大小已排序数组中的中位数
- 笔试题:求两个乱序数组的共公数组
- 递归求两个数组的中位数(或下中位数)
- 求两个有序数组的中位数
- 求两个有序数组的中位数
- 求两个有序数组的中位数
- 求两个有序数组的中位数
- 求两个有序数组的中位数
- 求这两个数组的中位数
- 通向架构师的道路(第二十二天)万能框架spring(四)使用struts2
- eclipse 内存不足OutOfMemoryError设置
- 自学日语第一天,第一课。
- 通向架构师的道路(第二十三天)maven与ant的奇妙整合
- jQuery选择器-WEB自动化测试提速之利剑
- 求两个已序数组的中位数
- fatal error C1189错误
- JavaScript定时器
- [小说]魔王冢(49)登徒子
- ort_tasks.c
- L4 Fiasco调度结构
- 通向架构师的道路(第二十四天)之Oracle性能调优-朝拜先知之旅
- 使用HQL查询符合条件的前n行语句
- 求助