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)).
Example 1:
nums1 = [1, 3]
nums2 = [2]
The median is 2.0
Example 2:
nums1 = [1, 2]
nums2 = [3, 4]
The median is (2 + 3)/2 = 2.5
题目大意:
给你两个长度分别为m和n的有序数列,将他们排序成为一个数组,并求中间元素的平均值.时间复杂度为O(log(m+n))
看见这个题第一反应就是归并排序,这个题目给的就是有序数列,所以更简单,只需要合并数组即可.题目要求是计算中间元素的平均值,如果合并完成后数列长度为奇数,那么中间元素只有一个,如果为偶数,中间元素有两个,那我们在合并时就不需要把数组都遍历,只找到前一半+1的数据即可.
class Solution {
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int i = 0, j = 0, k = 0;
int len1 = nums1.length;
int len2 = nums2.length;
int res[] = new int[len1+len2];
double med;
int mid = (len1 + len2) / 2;
//合并数组
//判断两个数组是否遍历完,以及结果数组的长度是否为一半
while(i < len1 && j < len2 && k < mid+1){
if(nums1[i] < nums2[j]){
res[k] = nums1[i];
k++;
i++;
}else{
res[k] = nums2[j];
k++;
j++;
}
}
//如果nums2遍历完但是还没找到中间的元素,继续遍历nums1
while(k < mid + 1 && i < len1){
res[k] = nums1[i];
i++;
k++;
}
//如果nums1遍历完但是还没找到中间的元素,继续遍历nums2
while(k < mid + 1 && j < len2){
res[k] = nums2[j];
j++;
k++;
}
//判断中间元素有一个还是两个
if((len1 + len2) % 2 == 0){
med = (double)(res[mid] + res[mid-1])/2;
}else{
med = (double)res[mid];
}
return med;
}
}
还有一种二分的方法,来自http://blog.csdn.net/hk2291976/article/details/51107778,里面分析很详细,我就不贴过来了.
只是在下面的代码中,和分析中有所不同的是把所有的数组长度都*2,那么都变成了偶数数组
代码:
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int n = nums1.size();
int m = nums2.size();
if(n > m) //保证数组1一定最短
return findMedianSortedArrays(nums2,nums1);
int L1,L2,R1,R2,c1,c2,lo = 0, hi = 2*n; //我们目前是虚拟加了'#'所以数组1是2*n长度
while(lo <= hi) //二分
{
c1 = (lo+hi)/2; //c1是二分的结果
c2 = m+n- c1; //寻找的是第m+n个和第m+n+1个元素,在数组中的下标为m+n-1和m+n
//判断边界情况并对它们赋值
L1 = (c1 == 0)?INT_MIN:nums1[(c1-1)/2]; //赋值时候就还原数组的位置
R1 = (c1 == 2*n)?INT_MAX:nums1[c1/2];
L2 = (c2 == 0)?INT_MIN:nums2[(c2-1)/2];
R2 = (c2 == 2*m)?INT_MAX:nums2[c2/2];
if(L1 > R2)
hi = c1-1;
else if(L2 > R1)
lo = c1+1;
else
break;
}
return (max(L1,L2)+ min(R1,R2))/2.0;
}
};