LeetCode_0004_寻找两个有序数组的中位数

本文介绍了一种在O(log(m+n))时间复杂度内寻找两个有序数组中位数的方法,通过二分法在两个数组中查找第k个元素,提供了C语言和Java的实现代码。

0004 寻找两个有序数组的中位数

题目链接:https://leetcode-cn.com/problems/median-of-two-sorted-arrays/

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。

请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。

你可以假设 nums1 和 nums2 不会同时为空。

示例 1:

nums1 = [1, 3]

nums2 = [2]

则中位数是 2.0

示例 2:

nums1 = [1, 2]

nums2 = [3, 4]

则中位数是 (2 + 3)/2 = 2.5

思路

  1. 要求时间复杂度为O(log(m+n)),就想到二分法
  2. 因为是两个从小到大的有序数组,查找中位数,就是查找第(nums1Size + nums2Size + 1) / 2和(nums1Size + nums2Size + 2) / 2两个数的均值
  3. 在两个数组查找第k个数,利用二分法,每次在两个数组查找第k/2个数,去掉小的那个数组前k/2个,再在接下来的数组中找,直到找到
  4. 注意边界条件,例如数组长度小于k/2

解法

1.C语言版
#define MIN(A, B) ((A) < (B) ? (A) : (B))

// 找到第K个数
int findKth(int* nums1, int nums1Size, int* nums2, int nums2Size, int k)
{
    if(nums1Size == 0) return nums2[k-1];
    if(nums2Size == 0) return nums1[k-1];
    if(k == 1) return MIN(nums1[0], nums2[0]);
	// 比较nums1和nums2的第k/2位,注意size比k/2小的情况
    int i = MIN(nums1Size, k / 2), j = MIN(nums2Size, k / 2);
	// 如果nums1的第i位大于nums2的第j位,那就去掉nums2的前j位,从nums2 + j开始,查找第k-j个
    if (nums1[i - 1] > nums2[j - 1])
    {
        return findKth(nums1, nums1Size, nums2 + j, nums2Size - j, k - j);
    } else
    {
        return findKth(nums1 + i, nums1Size - i, nums2, nums2Size, k - i);
    }
    return 0;
}
double findMedianSortedArrays(int* nums1, int nums1Size, int* nums2, int nums2Size) {
    return (findKth(nums1, nums1Size, nums2, nums2Size, (nums1Size + nums2Size + 1) / 2) +
            findKth(nums1, nums1Size, nums2, nums2Size, (nums1Size + nums2Size + 2) / 2)    ) / 2.0;
}
2.Java版
	/**
     * 查找中位数
     * @param nums1 数组1
     * @param nums2 数组2
     * @return
     */
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        return (findKthNum(nums1, 0, nums2, 0, (nums1.length + nums2.length + 1) / 2) + 
                findKthNum(nums1, 0, nums2, 0, (nums1.length + nums2.length + 2) / 2)) / 2.0;
      
    }
    /**
     * 从有序数组中查找第k个的数
     * @param nums1 数组1
     * @param i 数组1要计算的起始位置
     * @param nums2 数组2
     * @param j 数组2要计算的起始位置
     * @param k 查找第k个数
     * @return 第k个数
     */
    public int findKthNum(int[] nums1, int i, int[] nums2, int j, int k) {
        if (i == nums1.length)
            return nums2[j + k - 1];
        if (j == nums2.length)
            return nums1[i + k - 1];
        if (k == 1) 
            return Math.min(nums1[i], nums2[j]);
        int index1 = Math.min(i + k / 2, nums1.length);
        int index2 = Math.min(j + k / 2, nums2.length);
        if (nums1[index1 - 1] > nums2[index2 - 1])
            return findKthNum(nums1, i, nums2, index2, k - index2 + j);
        else
            return findKthNum(nums1, index1, nums2, j, k - index1 + i);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

aabond

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值