作者:静水流风
求两个有序数组的中位数,一般都是用递归方式来实现。
我自己写了一个非递归实现版本,供大家参考。如果有bug,请不吝赐教。
此函数求在元素总数为奇数时求出唯一中位数,在偶数情况下,求出下中位数。
该算法的时间复杂度为O(k), k为两数组中较短数组的长度。
int find_median(int *a, int lengtha, int *b, int lengthb)
{
assert(lengtha > 0); assert(lengthb > 0);
int *sa = lengtha <= lengthb ? a : b;
int *la = lengtha <= lengthb ? b : a;
const int lens = lengtha <= lengthb ? lengtha: lengthb;
const int lenl = lengtha <= lengthb ? lengthb: lengtha;
const int c = (lens + lenl -1) / 2;
int ls = 0;
int us = lens - 1;
while (ls <= us)
{
const int cs = (us + ls) / 2;
const int cl = c - cs;
if (sa[cs] < la[cl])
{
if (ls != cs)
ls = cs;
else if (cl == 0 || sa[cs] >= la[cl-1])
return sa[cs];
else if (us == cs)
return la[cl-1];
else
ls = cs + 1;
}
else if (sa[cs] > la[cl])
{
if (us != cs)
us = cs;
else if (cs == 0 || la[cl] >= sa[cs-1])
return la[cl];
else
us = cs - 1;
}
else
{
return sa[cs];
}
}
assert(0);
return 0;
}
算法思路:
1.采用分而治之。
2.以短数组为中心,以折半方式逐步缩小范围,以耗尽短数组。
附上测试程序:
#include <iostream>
#include <assert.h>
#include <vector>
#include <algorithm>
// 编译时,请在此处插入find_median的实现体
int test_find_median(int *A, int sizeA, int *B, int sizeB)
{
for (int i=0; i< sizeA; i++) std::cout << A[i] << " ";
std::cout << std::endl;
for (int i=0; i< sizeB; i++) std::cout << B[i] << " ";
std::cout << std::endl;
const int median = find_median(A,sizeA,B,sizeB);
std::cout<<"my median : "<< median <<std::endl;;
std::vector<int> a(A, A+sizeA);
a.insert(a.end(), B, B+sizeB);
std::sort(a.begin(), a.end());
const int stl_median = a[(a.size()-1)/2];
std::cout<<"stl median : "<< stl_median <<std::endl;;
assert(stl_median == median);
return 0;
}
int main(int argc, char* argv[])
{
{
int A[] = {5,6,7} ;
int B[] = {2,4};
test_find_median(A, sizeof(A)/sizeof(int), B, sizeof(B)/sizeof(int));
}
{
int A[] = {1,3,5} ;
int B[] = {6,7};
test_find_median(A, sizeof(A)/sizeof(int), B, sizeof(B)/sizeof(int));
}
{
int A[] = {1,3,5} ;
int B[] = {2,4};
test_find_median(A, sizeof(A)/sizeof(int), B, sizeof(B)/sizeof(int));
}
{
int A[] = {1,2,3,6,8} ;
int B[] = {6,7,8,9,10};
test_find_median(A, sizeof(A)/sizeof(int), B, sizeof(B)/sizeof(int));
}
{
int A[] = {1,3,5,7,9,11} ;
int B[] = {2,4,6,8,10,12};
test_find_median(A, sizeof(A)/sizeof(int), B, sizeof(B)/sizeof(int));
}
{
int A[]={2};
int B[]={1,3,5};
test_find_median(A, sizeof(A)/sizeof(int), B, sizeof(B)/sizeof(int));
}
{
int A[]={1,3,5,7,8,9,10};
int B[]={2,4,6,10,11,12,13,14,17,19,20};
test_find_median(A, sizeof(A)/sizeof(int), B, sizeof(B)/sizeof(int));
}
return 0;
}