这个题目的时间复杂度最小可以是O(logn);
解析:设A=(11,13,15,17,19)B=(2,4,6,8,20);
第一种想法:把A和B混合到一起再找中位数,这时候时间复杂度是O(n);
第二种想法:将中位数左右两边依次同时减去等长的元素,中位数不变。
A的中位数是15;B的中位数是6;因为A和B都是等长升序序列,说明A和B混合之后的中位数 6<=Mid<=15这时候将6的左边和15的右边删去相同数目也就是
A=(11,13,15);B=(6,8,20);
//这个两个数组合并的中位数和之前A=(11,13,15,17,19)
B=(2,4,6,8,20)合并的中位数一样
此时A的中位数是13;B的中位数是8;同理
Mid的范围缩小为 8<=Mid<=13 左右删去相同的数量的元素
A=(11,13);B=(8,20);
此时A的中位数是11;B的中位数是8;
(偶数情况下,下面有解释)8<Mid<=11 此时当删去13时8的左边没有元素为了保持平衡应该删去8;
此时A=(11);B=(20);所以A和B序列的中位数是11
【当序列分别为偶数时中位数不可能等于A和B较小的中位数,
因为例如A的中位数大,A的右侧的数包括A比左侧的数大2,A和B合并后最理想的可能A的中位数的左侧全部比B的中位数小,即使这样合并后B的中位数的右边的数的个数要比左边的数的个数大2;图示:
A=(1,2,6,7,8,9);B=(3,4,5,10,11,12)
A和B(1,2,3,4,5,6,7,8,9,10,11,12)
这样合并后5右边的数的个数要比左边的数的个数大2,而偶数序列中位数右边要比左边大1,所以不可能是B的中位数】
代码如下:
int Search(int A[], int B[], int n) {
int s1 = 0, d1 = n - 1, m1;//A的首位数、中位数、末位数
int s2 = 0, d2 = n - 2, m2;//B的首位数、中位数、末位数
while (s1 != d1 || s2 != d2) {
m1 = (s1 + d1) / 2;
m2 = (s2 + d2) / 2;
if (A[m1] == B[m2]) //当两个中位数相等,即为所求中位数
return A[m1];
else if (A[m1] < B[m2]) {
if ((s1 + d1) % 2 == 0) { //当元素个数为奇数
s1 = m1; //舍弃A中间点以前部分,保留中间点
d2 = m2; //舍弃B中间点以后部分,保留中间点
}
else{ //当元素个数为奇数
s1 = m1 + 1; //舍弃A中间点以前部分,不保留中间点
d2 = m2; //舍弃B中间点以后部分,保留中间点
}
}
else {
if ((s2 + d2) % 2 == 0) {
d1 = m1;
s2 = m2;
}
else {
d1 = m1;
s2 = m2 + 1;
}
}
}
return A[s1] < B[s2] ? A[s1] : B[s2];
}