力扣-寻找两个正序数组的中位数

今日没有缺席。十一月的最后一天,收到了大物成绩。考场上的发挥决定了做题家的上限,对知识的温习程度兜底分数的下限。

在这里插入图片描述
二分法

有序数组 找中位数 时间复杂度O(log(m+n))

中位数的原理
两个序列合并的中位数,相当于在每个序列找到一个分割位置,这个位置符合:
在这里插入图片描述即有两个分割条件:数量总和条件、数字大小条件

#include <limits.h>

#define MAX(a, b) (((a) >= (b)) ? (a) : (b))
#define MIN(a, b) (((a) <= (b)) ? (a) : (b))


double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size){
    int halfSize;
    int head1, tail1, half1, half2;
    int nums1Left, nums1Right, nums2Left, nums2Right;
    double ret;

    //确保nums1Size比较小
    if(nums1Size > nums2Size){
        return findMedianSortedArrays(nums2, nums2Size, nums1, nums1Size);
    }

    //插空后,nums1和nums2的长度均为2numsSize+1,halfSize为两个合起来的长度的一半。
    halfSize = nums1Size + nums2Size;

    //开始对nums1进行二分
    head1 = 0;
    tail1 = 2 * nums1Size;

    //小于等于可包含为空的情况
    while (head1 <= tail1) {
        half1 = head1 + (tail1 - head1) / 2;
        //由于确保nums1Size比较小,half2肯定大于0
        half2 = halfSize - half1;

        //考虑边界情况
        nums1Left = (half1 == 0) ? INT_MIN : nums1[(half1 - 1) / 2];
        nums2Left = (half2 == 0) ? INT_MIN : nums2[(half2 - 1) / 2];

        nums1Right = (half1 == 2 * nums1Size) ? INT_MAX : nums1[half1 / 2];
        nums2Right = (half2 == 2 * nums2Size) ? INT_MAX : nums2[half2 / 2];

        if (nums1Left > nums2Right) {
            tail1 = half1 - 1;
        } else if (nums2Left > nums1Right ) {
            head1 = half1 + 1;
        } else {
            break;
        }
    }

    ret = (MAX(nums1Left, nums2Left) + MIN(nums1Right, nums2Right)) / 2.0;

    return ret;
}

limits.h 头文件决定了各种变量类型的各种属性。定义在该头文件中的宏限制了各种变量类型(比如 char、int 和 long)的值。

这些限制指定了变量不能存储任何超出这些限制的值,例如一个无符号可以存储的最大值是 255。

二分法查找,也称为折半法,是一种在有序数组中查找特定元素的搜索算法。

二分法查找的思路如下:

(1)首先,从数组的中间元素开始搜索,如果该元素正好是目标元素,则搜索过程结束,否则执行下一步。

(2)如果目标元素大于/小于中间元素,则在数组大于/小于中间元素的那一半区域查找,然后重复步骤(1)的操作。

(3)如果某一步数组为空,则表示找不到目标元素。

链接:https://blog.csdn.net/u012194956/article/details/79103843

***数量总和条件***满足:
使用符号填充方法,不管是奇偶的序列,填充后都会变成奇数序列。
在这里的必要性很重要,因为分割位置只需要选择序列1的任意一个数或字符上,均可在序列2找到某一个数或字符,符合分割后左边的数字总和等于右边的数字总和。

[1,2,3]
[1,1,3,3]

填充后

[#,1,#,2,#,3,#]
[#,1,#,1,#,3,#,3#]

填充后分割,只需要两个序列的位置index为:

half1 + half2 == halfSize == nums1Size + nums2Size

half1和half2表示扩充后的序列的分割位置,nums1Size和nums2Size表示原序列的总长度。
随后half1调整位置,half2只需要相应调整位置即可。

***数字大小条件***满足:
判断:1左<2右;2左<1右

  • 若分割在数字上,则分割左右均取该数字;
  • 若分割在字符上,则取分割左右的数字。

中位数的获取=分割点左边的最大值+分割点右边的最小值的平均数。

边界条件

  • 序列为空
  • 取到最左最右的情况
    在这里插入图片描述
    参照:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/solution/cyu-yan-er-fen-fa-by-pang-san-jin-3/
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值