版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huanghaocs/article/details/81638741
1.问题描述
给定两个有序数组nums1和nums2,返回这两个数组合并的有序数组的中位数。
例:nums1 = [1,2], nums2 = [3,4,5], 返回结果是3;
nums1 = [1,2,3], nums2 = [4,5,6], 返回结果是3.5。
2.解决方法
(1)直接把这两个数组合并成一个有序数组,然后取中位数。时间复杂度O(m+n),空间复杂度O(m+n)
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int len1 = nums1.length;
int len2 = nums2.length;
int[] nums = new int[len1+len2]; // 定义数组空间,存放两个数组合并结果
int index1 = 0, index2 = 0, i=0;
// 先扫描两个数组大小重叠的部分
while(index1 < len1 && index2 < len2){
if(nums1[index1] < nums2[index2]){
nums[i++] = nums1[index1];
index1++;
}else{
nums[i++] = nums2[index2];
index2++;
}
}
// nums2扫描完毕,剩余nums1元素都大于nums2元素
while(index1 < len1){
nums[i++] = nums1[index1];
index1++;
}
// nums1扫描完毕,剩余nums2元素都大于nums1元素
while(index2 < len2){
nums[i++] = nums2[index2];
index2++;
}
double med = 0;
int len = nums.length;
// 总共为偶数个,中间值是数组中间两个元素平均
if(len % 2 == 0){
med = (nums[len/2 - 1] + nums[len/2])*1.0 / 2;
}else{ // 总共为奇数个,中间值是就是数组中间的元素
med = nums[len/2];
}
return med;
}
(2)考虑合并后求的是中位数,把数组分成两块,只要找到中间那个数就可以。
public double findMedianSortedArrays(int[] nums1, int[] nums2) {
int m = nums1.length;
int n = nums2.length;
// 先判断是否有一个数组为空
double med = 0;
int k = (m+n) / 2;
if(m == 0){
if(n % 2 == 0)
med = (nums2[n/2-1] + nums2[n/2])*0.5;
else
med = nums2[n/2];
return med;
}
if(n == 0){
if(m % 2 == 0)
med = (nums1[m/2-1] + nums1[m/2])*0.5;
else
med = nums1[m/2];
return med;
}
// 不为空,保证len(nums1) < len(nums1),如果不是交换位置
if(m > n){
return findMedianSortedArrays(nums2, nums1);
}
int iMin = 0, iMax = m;
while(iMin <= iMax){
int i = (iMin + iMax) / 2;
int j = (m + n + 1) /2 - i;
if(j != 0 && i != m && nums2[j-1] > nums1[i])
iMin = i + 1;
else if(i != 0 && j != n && nums1[i-1] > nums2[j])
iMax = i - 1;
else{
int maxLeft = 0;
if(i == 0)
maxLeft = nums2[j-1];
else if(j == 0)
maxLeft = nums1[i-1];
else
maxLeft = Math.max(nums1[i-1], nums2[j-1]);
if((m + n) % 2 == 1) // 奇数直接返回结果
return maxLeft;
int minRight = 0;
if(i == m)
minRight = nums2[j];
else if(j == n)
minRight = nums1[i];
else
minRight = Math.min(nums2[j], nums1[i]);
return (maxLeft + minRight) / 2.0; // 偶数需要取半
}
}
return 0;
}