nums1和 nums2,长度分别为m和n,在最大时间复杂度为 O(log(m+n))的要求下找到将两个数组合并成的有序数组 nums3的中位数。A=[1,3,8,10,11], B=[2,4,6,7,9], 将两数组有序合并后得到 C=[1,2,3,4,6,7,8,9,10,11],此时中位数为 (6+7)/2=6.5.C的中位数,但是发现构造数组 C需要手动将两个数组合并,这将直接导致我们的时间复杂度达到 O(n)。并且令人头大的是当合并数组C的长度为奇数或者偶数时,中位数的求法甚至都不一样。因此,我们需要另辟蹊径。
partitionA=2分为左partition和右partition,同样,数组B被 partitionB=3分为左partition和右partition。partitionA和 partitionB必须满足以下关系。
partitionA + partitionB == C.Length() / 2
A[partitionA - 1] <= B[partitionB]
B[partitionB - 1] <= A[partitionA]
median = [max(A[partitionA-1],B[partitionB-1]) + min(A[partitionA],B[partitionB])] / 2
6=max(3,6), 7=max(7,8), 因此中位数为 (6+7)/2=6.5。partitionA或 partitionB 中任意一个值,我们就能推出另外一个值,并且求得中位数!partitionB的值。数组B的长度为5, partitionB可以是0到5的任意一个值,那么我们必须要把正确的值试出来,怎么试呢?我们可以利用数组A和B的有序性进行二分查找!以下迭代将用伪得不能再伪的伪代码来展示(二分查找窗口从 [0,5]开始)。
start = ;
end = 5;
partitionB = (start + end) / 2 = 2;
partitionA = C.Length() / 2 - 2 = 5 - 2 = 3;
A[partitionA - 1] = 8
A[partitionA] = 10
B[partitionB - 1] = 4
B[partitionB] = 6

A[partitionA-1]>B[partitionB], 显然不符合我们上面的不等式,值得注意的是,此时的情况是A数组的左partition的最大值大于B的右partition的最小值,因此我们的partitionB应该向右边移动,也就是说二分查找的窗口将从 [0,5] 变为 [partitionB+1,5]也就是 [3,5]。于是我们开始第二轮迭代。
start = 3;
end = 5;
partitionB = (start + end) / 2 = 4;
partitionA = C.Length() / 2 - 4 = 5 - 4 = 1;
A[partitionA - 1] = 1
A[partitionA] = 3
B[partitionB - 1] = 7
B[partitionB] = 9

B[partitionB-1]>A[partitionA]),可是此时的情况与上一轮不同,此时B数组的左partition的最大值比A数组的右partition的最小值大,因此partitionB应该向左移动。二分查找窗口将从 [3,5]变为 [3,partitionB-1]也就是 [3,3]。于是我们开始第三轮迭代。
start = 3;
end = 3;
partitionB = (start + end) / 2 = 3;
partitionA = C.Length() / 2 - 2 = 5 - 3 = 2;
A[partitionA - 1] = 3
A[partitionA] = 8
B[partitionB - 1] = 6
B[partitionB] = 7
[max(3,6)+min(8,7)]/2=6.5partitionB的值为5时, partitionA求得为0,这时 partitionA-1为-1,同理, partitionB的值为0时, partitionA的值为5,超过了数组的最大索引4。这种极限情况如下图所示。
A[partitionA-1]不存在时,赋值给其 INTMIN, 因为如果A的左partition不存在,在做比较的时候任何数都可以比它里面的所有元素大。当 A[partitionA]不存在时,赋值给其 INTMAX,此时同理,如果A的右partition不存在,那么做比较的时候任何数都可以比他里面的所有元素小。对B来说同理。partitionA和 partitionB的最小值即可。
double findMedianSortedArrays(vector<int>& A, vector<int>& B) {int lenA = A.size();int lenB = B.size();if (lenA > lenB) {return findMedianSortedArrays(B, A);}int start = ;int end = lenA;while (start <= end) {int partitionA = (start + end) / 2;int partitionB = (lenA + lenB) / 2 - partitionA;int leftA = (partitionA > ) ? A[partitionA - 1] : INT_MIN;int rightA = (partitionA < lenA) ? A[partitionA] : INT_MAX;int leftB = (partitionB > ) ? B[partitionB - 1] : INT_MIN;int rightB = (partitionB < lenB) ? B[partitionB] : INT_MAX;if (leftA <= rightB && leftB <= rightA) {if ((lenA + lenB) % 2) {return min(rightA, rightB);} else {return (max(leftA, leftB) + min(rightA, rightB)) / 2.;}} else if (leftA > rightB) {end = partitionA - 1;} else {start = partitionA + 1;}}return ;}
!!来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/69966956/viewspace-3138033/ ,如需转载,请注明出处,否则将追究法律责任。