网上的很多关于此题的做法都有Bug,故想了一下午,终于想到一个自我感觉Bug比较少的解法(可能还有Bug,欢迎大家指正)。
/*
* 求两个有序数组合并后的中位数,时间复杂度O(logn)
*/
#include <iostream>
#include <string>
using namespace std;
/*
*1 2 3 4 5 6 7 8,此时left=right=5,表示如果一个数的右边
有至少right个数,那么该数及左边都不是中位数
对于奇数的话,统一起见
*/
void getMid(int *arr1, int n1, int *arr2, int n2)
{
int left = (n1+n2+1)/2+1;
int right = left;
int begin1 = 1;
int begin2 = 1;
int end1 = n1;
int end2 = n2;
bool flag = false;
while(left!=2 || right!=2)
{
if(begin1>end1 || begin2>end2) //奇数时,中位数就一个,此时会出现这种情况
{
flag = true;
break;
}
int mid1 = (begin1+end1)/2;
int mid2 = (begin2+end2)/2;
int loffset = 0;
int roffset = 0;
if(arr1[mid1] == arr2[mid2])
{
cout<<arr1[mid1]<<endl;
}
else if(arr1[mid1] < arr2[mid2])
{
if(mid1-begin1+mid2-begin2+2 >= left)
{
roffset = end2 - mid2;
if(roffset == 0 && right!=2)
{
if(arr2[end2] > arr1[end1])
{
end2--;
}
else
{
end1--;
}
right--;
continue;
}
}
else
{
if(end2-mid2 > 1)
{
roffset = 1;
}
}
if(end1-mid1+end2-mid2+2 >= right)
{
loffset = mid1 - begin1;
if(loffset == 0 && left!=2)
{
if(arr1[begin1] < arr2[begin2])
{
begin1++;
}
else
{
begin2++;
}
left--;
continue;
}
}
else
{
if(mid1-begin1 > 1)
{
loffset = 1;
}
}
begin1 += loffset;
end2 -= roffset;
left -= loffset;
right -= roffset;
}
else
{
if(end1-mid1+end2-mid2+2 >= right)
{
loffset = mid2 - begin2;
if(loffset == 0 && left!=2)
{
if(arr1[begin1] < arr2[begin2])
{
begin1++;
}
else
{
begin2++;
}
left--;
continue;
}
}
else
{
if(mid2-begin2 > 1)
{
loffset = 1;
}
}
if(mid1-begin1+mid2-begin2+2 >= left)
{
roffset = end1 - mid1;
if(roffset == 0 && right!=2)
{
if(arr2[end2] > arr1[end1])
{
end2--;
}
else
{
end1--;
}
right--;
continue;
}
}
else
{
if(end1-mid1 > 1)
{
roffset = 1;
}
}
begin2 += loffset;
end1 -= roffset;
left -= loffset;
right -= roffset;
}
}
if(flag)
{
if(begin1>end1)
{
for(int i=begin2+left-2; i<=end2-right+2; i++)
{
cout<<arr2[i]<<endl;
}
}
else
{
for(int i=begin1+left-2; i<=end1-right+2; i++)
{
cout<<arr1[i]<<endl;
}
}
return;
}
for(int i=begin1; i<=end1; i++)
{
cout<<arr1[i]<<endl;
}
for(int i=begin2; i<=end2; i++)
{
cout<<arr2[i]<<endl;
}
}
int main(int argc,char* argv[])
{
int arr1[]={0,1,3,6,8};
int arr2[]={0,2,4,5,7};
getMid(arr1, 4, arr2, 4);
return 0;
}