There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
根据返回值为double,输入为int可知,如果m+n为偶数,那么返回值就应该是最中间两个数的均值,否则返回最中间的数值。
这题我的思路是两头往中间靠拢,因为输入为数组的缘故,某些情况下可以直接计算出中值的index,提高执行速度。
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
//两个数组无效
if ((nums1 == null && nums2 == null) ||
(nums1 == null && nums2.length == 0) ||
(nums2 == null && nums1.length == 0) ||
(nums1.length == 0 && nums2.length == 0)){
return 0;
}
//一个数组无效
if (nums1 == null || nums2 == null || nums1.length == 0 || nums2.length == 0){
int[] tmp = (nums1 == null || nums1.length == 0) ? nums2 : nums1;
int len = tmp.length;
//长度为偶数
if ((len&1) == 0){
return (double)(tmp[len/2-1]+tmp[len/2])/2;
}
//奇数
return tmp[len/2];
}
int b1 = 0, e1 = nums1 == null ? 0 : nums1.length-1,
b2 = 0, e2 = nums2 == null ? 0 : nums2.length-1;
//有交叉
while (b1 <= e1 || b2 <= e2){
//某一数组走到尽头
if ((b1 > e1 && b2 <= e2) || (b1 <= e1 && b2 > e2)){
int b = b1 > e1 ? b2 : b1, e = b1 > e1 ? e2 : e1;
int[] tmp = b1 > e1 ? nums2 : nums1;
int len = b+e;
if ((len&1) == 0){
return tmp[len/2];
}
return (double)(tmp[len/2]+tmp[len/2+1])/2;
}else if (b1 == e1 && b2 == e2){ //两个数组都走到尽头
return (double)(nums1[b1]+nums2[b2])/2;
}
if (nums2[b2] <= nums1[b1]){
b2++;
}
else if (nums1[b1] < nums2[b2]){
b1++;
}
if (nums1[e1] >= nums2[e2]){
e1--;
}
else if (nums2[e2] > nums1[e1]){
e2--;
}
}
return 0;
}
也可以这样:因为知道两数组的总长度,因此可以知道中位数前后有多少个元素,于是设置两个指针,从两个数组的尾部开始移动,直到经过的元素个数达到总长度的一半(这个是受别人启发的,思维还需要锻炼)。
//只从一个方向移动,直到过滤掉(m+n)/2个元素
public static double findMedianSortedArrays(int[] nums1, int[] nums2){
//两个数组无效
if ((nums1 == null && nums2 == null) ||
(nums1 == null && nums2.length == 0) ||
(nums2 == null && nums1.length == 0) ||
(nums1.length == 0 && nums2.length == 0)){
return 0;
}
//一个数组无效
if (nums1 == null || nums2 == null || nums1.length == 0 || nums2.length == 0){
int[] tmp = (nums1 == null || nums1.length == 0) ? nums2 : nums1;
int len = tmp.length;
//长度为偶数
if ((len&1) == 0){
return (double)(tmp[len/2-1]+tmp[len/2])/2;
}
//奇数
return tmp[len/2];
}
int len = nums1.length + nums2.length;
int midLen = len/2, end1 = nums1.length-1, end2 = nums2.length-1, preVal = 0, curVal = 0;
for (int i=0; i<midLen+1; i++){
if (end1 >= 0 && (end2 < 0 || nums1[end1] >= nums2[end2])){
preVal = curVal;
curVal = nums1[end1];
end1--;
}
else if (end2 >= 0 && (end1 < 0 || nums2[end2] >= nums1[end1])){
preVal = curVal;
curVal = nums2[end2];
end2--;
}
}
if ((len&1) == 0){
return (double)(preVal+curVal)/2;
}
else {
return curVal;
}
}