网上的很多关于此题的做法都有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; }