leetcode.4寻找两个有序数组的中位数(C语言)

1、问题描述

在这里插入图片描述
这道题的边界判断比较的多,如果是边测试边界边编写判断语句的话,一点点的总能成功(我就是这样),如果要一口气分析的话属实有点麻烦。

下面是具体思路:

1、我们总能用一刀将两个数组各切成两半。
在这里插入图片描述
切完之后呢,在nums1中,切线左边所有元素肯定小于右边所有元素,即L_MAX1 <= R_MIN1 。同样,在nums2中,L_MAX2 <= R_MIN2

2、这一刀我们应该切在哪里呢?
重点:如果我们能切下一刀,满足
L_MAX1 <= R_MIN2 && L_MAX2 <= R_MIN_1

那么,假设 numsSize1 + numsSize2 = 奇数,中位数就是切线左边最大的数; numsSize1 + numsSize2 = 偶数,中位数就是切线左边最大的数与切线右边最小的数的平均数。
如上图所示,切线左边最大的是nums1的3,切线右边最小的是nums2的4,则中位数就是3.5。

其实我们可以将其归结为寻找两个有序数组的第k小的元素。
nums1[ i ] , nums2[ j ]
满足: i + j = k。
那么寻找中位数呢

int size_left = (nums1Size + nums2Size + 1)/2

满足 i + j = size_left 即可。

2、通过代码解释更清楚

以下代码都是按顺序解释,没有删减

2.1、定义与初始化

double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size){
    int size_left = (nums1Size + nums2Size + 1)/2; //表示两个数组合并后中位数左边的个数。
    int i = 0, j = size_left-i; // i + j = size_left
    // i负责从头遍历nums1 , j 负责从尾端后往前遍历nums2
    
    double max_left,min_right; // max_left 用来存储切线左边最大值,min_right 用来存储切线右边最小值

我们将长度较小的数组放在nums1 中,方便之后的操作。

 if(nums1Size > nums2Size){
        int *temp,t;
        temp = nums1;
        nums1 = nums2;
        nums2 = temp;
        t = nums1Size;
        nums1Size = nums2Size;
        nums2Size = t;
    }

2.2、中间部分
我将if else 语句分开解释,便于理顺思路。

if(nums1Size==0 && nums2Size==0) // 若两个数组都为空,则直接返回0
        return 0;
 else if(nums1Size==0){ // 如果第一个数组为空,那我们直接从第二个数组找到中位数就可以了。
        max_left = nums2[(nums2Size-1)/2];
        min_right = nums2[nums2Size/2];
    }
    else{
        while(i<=nums1Size){ // 当i有效的时候
            if(i == nums1Size){ // 详见情况【1】
                if(j==0)
                    max_left = nums1[i-1]; 
                else
                    max_left = nums1[i-1]>nums2[j-1]?nums1[i-1]:nums2[j-1];
                min_right = nums2[j];
                break;
            }
            else if(nums1[i]>=nums2[j-1]){
                if(i==0){ // 详见情况【2】
                    if(j==nums2Size)
                        min_right = nums1[i];
                    else
                        min_right = nums1[i]<nums2[j]?nums1[i]:nums2[j];
                    max_left = nums2[j-1];
                    break;
                }
                // 若不是边界值则 正常判断。
                max_left = nums1[i-1]>nums2[j-1]?nums1[i-1]:nums2[j-1];
                min_right = nums1[i]<nums2[j]?nums1[i]:nums2[j];
                break;

            }
            else{   
                i++; // 继续往下一个元素遍历
                j = size_left-i; // 受i的约束,保持关系
            }    
        }
    }

边界值情况
在这里插入图片描述

// 最后判断奇偶数,输出中位数
if((nums1Size + nums2Size)%2 == 0)
        return (max_left+min_right)/2;
    else
        return max_left;

}

3、完整代码

double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size){
    int size_left = (nums1Size + nums2Size + 1)/2; //表示两个数组合并后中位数左边的个数。
    int i = 0, j = size_left-i;
    double max_left,min_right;
    
    if(nums1Size > nums2Size){
        int *temp,t;
        temp = nums1;
        nums1 = nums2;
        nums2 = temp;
        t = nums1Size;
        nums1Size = nums2Size;
        nums2Size = t;
    }

    if(nums1Size==0 && nums2Size==0)
        return 0;
    else if(nums1Size==0){
        max_left = nums2[(nums2Size-1)/2];
        min_right = nums2[nums2Size/2];
    } 
    else{
        while(i<=nums1Size){
            if(i == nums1Size){
                if(j==0)
                    max_left = nums1[i-1]; 
                else
                    max_left = nums1[i-1]>nums2[j-1]?nums1[i-1]:nums2[j-1];
                min_right = nums2[j];
                break;
            }
            else if(nums1[i]>=nums2[j-1]){
                if(i==0){
                    if(j==nums2Size)
                        min_right = nums1[i];
                    else
                        min_right = nums1[i]<nums2[j]?nums1[i]:nums2[j];
                    max_left = nums2[j-1];
                    break;
                }
                max_left = nums1[i-1]>nums2[j-1]?nums1[i-1]:nums2[j-1];
                min_right = nums1[i]<nums2[j]?nums1[i]:nums2[j];
                break;

            }
            else{   
                i++;
                j = size_left-i;
            }    
        }
    }
    
    if((nums1Size + nums2Size)%2 == 0)
        return (max_left+min_right)/2;
    else
        return max_left;

}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值