Leetcode 4. Median of Two Sorted Arrays

本文介绍了一种高效查找两个已排序数组合并后中位数的方法,采用二分搜索法实现,确保了时间复杂度为O(log(m+n))。通过实例演示了如何通过分割数组并比较边界元素来确定中位数。

题目:

There are two sorted arrays nums1 and nums2 of size m and n respectively.

Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

You may assume nums1 and nums2 cannot be both empty.

Example 1:

nums1 = [1, 3]
nums2 = [2]

The median is 2.0

Example 2:

nums1 = [1, 2]
nums2 = [3, 4]

The median is (2 + 3)/2 = 2.5

 

题意:

给定两个已经排好序的数组,我们需要找到两个数组合起来之后的中位数。

 

解法

首先,我们可以使用直接把两个数组融合,但是这样的复杂度为O(n+m),比题目说提出的O(log(m+n))要大,

随意我们得使用别的方法 

二分搜索法:

我们需要将两个数组分割,是它们的左半边相加的大小与右半边相加的大小一样,并且满足数组一的左边最大值小于或等于数组二右边的最小值,数组一右边的最小值大于或等于数组二左边的最大值

如以下所示:

array1= 1  ,  3  ,  8  , 9 ,11

array2 = 7   , 13 ,  15  , 18, 19

成功分割后的结果:

array1 =   1 , 3     ,8 , 9                 |             11                           

array2 =   7                                           |           13,15,18,19

 

这个时候求中位数就简单了,如果 两个数组长度之和为偶数,只需要找到左边最大值和右边最小值除2就行

如果为奇数,取左半边最大值即可。

 

下面的问题就是如何构造这样的分割,我们可以使用二分查找

首先我们根据数组长度,进行第一个次尝试分割,第一次 我们选取第一个数组的一半进行分割,对于上面的例子,分割点就是 (0+5)/2   =2       第二个数组被分割的点就是   (数组一的长度 + 数组二的长度+1)/2  - 数组一的分割点= (5+5+1)/2 -2=3

所以以上数组被分为

array1= 1  ,  3      |     8  , 9 ,11

array2 = 7   , 13 ,  15   |  18, 19

检查一下  3<18 满足 ,15 >8 不满足条件

继续调整分割

很明显需要将数组一的分割线向右移,我们继续二分尝试 (2+5)/2=3   那么数组二的分割线为  11/2-3=2

分割后

array1= 1  ,  3  ,8  |   9 ,11

array2 = 7   , 13        | 15   ,  18, 19

 

检查  13>9 依然不满足 继续二分

 

这一次我们就找到了满意的分割,之后进行判断结果即可。

代码:

class Solution {
    public double findMedianSortedArrays(int[] input1, int[] input2) {
        if (input1.length > input2.length) {
            return findMedianSortedArrays(input2, input1); // ensures 1st array is smaller than 2nd array
        }
        int x = input1.length;
        int y = input2.length;

        int low = 0;
        int high = x;
        while (low <= high) {
            int partitionX = (low + high) / 2;
            int partitionY = (x + y + 1) / 2 - partitionX;

            int maxLeftX  = (partitionX == 0) ? Integer.MIN_VALUE :  input1[partitionX - 1];      //如果左半边为空,把值设为最小,不影响后续的比较 
            int minRightX = (partitionX == x) ? Integer.MAX_VALUE : input1[partitionX];

            int maxLeftY  = (partitionY == 0) ? Integer.MIN_VALUE : input2[partitionY - 1];
            int minRightY = (partitionY == y) ? Integer.MAX_VALUE : input2[partitionY];

            if (maxLeftX <= minRightY && maxLeftY <= minRightX) {
                if ((x + y) % 2 == 0) {
                    return ((double) Math.max(maxLeftX, maxLeftY) + Math.min(minRightX, minRightY)) / 2;
                } else {
                    return (double) Math.max(maxLeftX, maxLeftY);
                }
            } else if (maxLeftX > minRightY) {
                high = partitionX - 1;
            } else {
                low = partitionX + 1;
            }
        }

    }
    
}

      

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值