两个有序数组中找中位数或者第K大的元素

RT,在两个有序数组中找中位数或者第K大的元素.

假设两个数组为A, B长度分别为m,n.分别是递增顺序。

可以采用的算法有很多:

首先想到的是类似MergeSort的方式,合并的同时找第K大元素,这个基本没难度,复杂度O(m + n)。

不过此算法并不是最优,还有Log级别复杂度的算法,此算法其实很简单,远没有很多网站的代码那么玄乎,以下一一道来:

首先明白几个前提:

1.如果是求中位数,(m + n)是奇数还是偶数对结果是很有影响的,具体的如果(m + n)是奇数,中位数唯一,如果是偶数就有两个中位数,怎么取舍就看要求了。

2.如果找到的第k大数(中位数类似)是 X ,如果X排在A中的 第Ax位置,X排序在B中的Bx位置,那么(Ax + Bx - 1) == k 是恒成立的。

明白了2中的前提后,我们就可以得到一个算法,在A数组中枚举X,加入在A中是第Ax个,那么可以反推B中第 (k + 1 - Ax)个以及相邻元素和X的大小关系就可以得到一个Log级别复杂度的算法:

简单点我们可以这么想:

1)先假设第k大数在A中,我们首先从A中第(m/(m + n)) * (k - 1)个元素开始检查其是否是第k个元素,假设其值为A1,然后看B中第(k + 1 - (m/(m + n)) * (k - 1)个元素(B1)和A1是否相等,或者 大于B中第(k + 1 - (m/(m + n)) * (k - 1))个元素,小于B中第(k + 1 - (m/(m + n)) * (k - 1))+ 1个元素。满足及可以知道A1即为所求。如果两个条件都不满足,请看2.

2)如果两个条件都不满足,那么需要判断第k个元素是处于 A1的左边还是右边,这个就是典型的分治思想。具体的来说:

             if A1 > B1  那么k可以排除肯定不在A[0, (m/(m + n)) * (k - 1)]以及B[(k + 1 - (m/(m + n)) * (k - 1))+ 1, n]中

             if A1< B1  那么k可以排除肯定不在A[ (m/(m + n)) * (k - 1), m]以及B[0, (k + 1 - (m/(m + n)) * (k - 1))]中.

             注意下临界条件(corner condition may not stastify, but the method is right)

第K个元素有可能在B中,同理可以假设在B中,然后再搜索一遍就可以查到。复杂度 log(m)+ log(n)

当然也可以两个数组一起找,总体代码如下:

 1     int kthsmallest(int *a,int m,int *b,int n,int k) {
 2         if (m == 0) {
 3             return b[k - 1];
 4         }
 5         if (n == 0) {
 6             return a[k - 1];
 7         }
 8         if (k == 1) {
 9             return (a[0] < b[0])?a[0]:b[0];
10         }
11         if (k == m + n) {
12             return (a[m - 1] > b[n - 1])?a[m - 1]:b[n - 1];
13         }
14         int i = ((double) m) / (m + n) * (k - 1);
15         int j = k - 1 - i;
16         if (j >= n) {
17             j = n - 1;
18             i = k - n;
19         }
20         if (((i == 0) || (a[i - 1] <= b[j])) && (b[j] <= a[i])) {
21             return b[j];
22         }
23         if (((j == 0) || (b[j - 1] <= a[i])) && (a[i] <= b[j])) {
24             return a[i];
25         }
26         if (a[i] <= b[j]) {
27             return kthsmallest(a + i + 1, m - i - 1, b, j, k - i - 1);
28         } else {
29             return kthsmallest(a, i, b + j + 1, n - j - 1, k - j - 1);
30         }
31 
32     }

 

 

posted @ 2012-12-26 23:42  David Luo  阅读(15874)  评论(1编辑  收藏  举报