反正作为菜鸡的我 这道题是真真正正难住了我,找了无数题解 看了n遍代码 才真正搞懂 所以我决定要好好把这道题撕一撕。
先把解析资料放这
是不是资料看得头大 让我通俗的讲一讲:
- 第一点
对于合并后的数组,其前一半的数组是不是肯定有前n个A数组中的数和前m
个B数组中的数组成,我要是能确定n和m是不是肯定能得出答案 ps:m+n是定值是Asize+Bsize的一半
所以肯定是有限个组合 所以只要n从1到Asize+Bsize的一半,就可以全部找出这些组合 - 第二点 如何确定某一个组合不合适
ai 和bj都要小于等于 ai+1 和bj+1这样才是合适的 否则不是合适的?想想为什么 从合并的角度出发
这是代码和注释
double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size){
if(nums1Size>nums2Size)//确保二分查找的次数最少
{
return findMedianSortedArrays(nums2,nums2Size,nums1,nums1Size);
}
int high = nums1Size;//一共这么多的插入点,比数据多一
int low = 0;
int m = (nums1Size+nums2Size+1)/2;//这个点要学习,可以在偶数时找到一半奇数时找到一办加1
while(low<=high)
{
int i =(high+low)/2;//这个是找到分割点哦,注意第i个分割点前面有i个数据
int j = m-i;//j是第二个序列取的数 注意:是第几个 所以引用时要【j-1】
if (j != 0 && i != nums1Size&& nums2[j-1] > nums1[i]){ // i 需要增大
low = i + 1;
}
else if (i != 0 && j != nums2Size&& nums1[i-1] > nums2[j]) { // i 需要减小
high = i - 1;
}
else//到达这一步就有两种可能,要不就是找到了,要不就是特殊情况
{
//接下来就是分情况讨论1,特殊情况 2,一般情况 然后每种情况分奇偶两种情况
//但后来发现可以合并
//注意:以下代码是精简过的 把情况给合并了,因为总数奇数时中位数只看左边,所以只要担心左边的元素会不会越界小于零,偶数时要看右边,所以要考虑是否越界
double leftmax = 0;
if(i == 0)//
{
leftmax = nums2[j-1] ; //此处建议用个图画一画 别太相信自己的想象力
}
else if(j == 0)
{
leftmax = nums1[i-1];
}
else{
leftmax = nums2[j-1]>nums1[i-1]?nums2[j-1]:nums1[i-1];
//大的数字排的更靠近中位数 不懂的话想想如果把他们归并排序是不是这样
}
if((nums1Size+nums2Size)%2==1)
return leftmax;//中位数要么是最左边的(当总数是奇数)要么是左边最大和右边最小 肯定先判断奇数
double rightmin = 0;
if(i == nums1Size)
{
rightmin = nums2[j];
}
else if(j == nums2Size)
{
rightmin=nums1[i];
}
else{
rightmin = nums1[i]<nums2[j]?nums1[i]:nums2[j];
}
return (rightmin+leftmax)/2.0;
}
}
return 0.0;
}