两个排序数组的中位数

原题

  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)).算法

题目大意

  两个排序数组,找这两个排序数组的中位数,时间复杂度为O(log(m+n))数组

解题思路

设数组A的长度为m, 数组B的长度为n, 两个数组都都是递增有序的。spa

求这两个数组的中位数.net

 

首先咱们看看中位数的特色,一个大小为n的数组,code

若是n是奇数,则中位数只有一个,数组中刚好有  (n-1)/2 个元素比中位数小。排序

若是n是偶数,则中位数有两个(下中位数和上中位数),这里咱们只求下中位数,对于下中位数,get

数组中刚好有(n-1)/2个元素比下中位数小。it

 

此题中,中位数只有一个,它前面有 c = (m+n-1)/2 个数比它小。中位数要么出如今数组A中,io

要么出如今数组B中,咱们先从数组A开始找。考察数组A中的一个元素A[p], 在数组A中,ast

有 p 个数比A[p]小,若是数组B中刚好有 c-p 个数比 A[p] 小, 则俩数组合并后就刚好有 c 个数比A[p]小,

因而A[p]就是要找的中位数。 以下图所示:

若是A[p] 刚好位于 B[c-p-1] 和 B[c-p] 之间,则 A[p] 是中位数

若是A[p] 小于 B[c-p-1] ,说明A[p] 过小了,接下来从 A[p+1] ~A[m-1]开始找

若是A[p] 大于 B[c-p] ,说明A[p] 太大了,接下来从 A[0] ~A[p-1]开始找。

若是数组A没找到,就从数组B找。

 

注意到数组A和数组B都是有序的,因此能够用二分查找。

  采用类二分查找算法

代码实现

public class Solution {
    /**
     * 004-Median of Two Sorted Arrays(两个排序数组的中位数)
     *
     * @param nums1
     * @param nums2
     * @return
     */
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {

        if (nums1 == null) {
            nums1 = new int[0];
        }

        if (nums2 == null) {
            nums2 = new int[0];
        }

        int len1 = nums1.length;
        int len2 = nums2.length;

        if (len1 < len2) {
            // 确保第一个数组比第二个数组长度大
            return findMedianSortedArrays(nums2, nums1);
        }

        // 若是长度小的数组长度为0,就返回前一个数组的中位数
        if (len2 == 0) {
            return (nums1[(len1 - 1) / 2] + nums1[len1 / 2]) / 2.0;
        }


        int lo = 0;
        int hi = len2 * 2;
        int mid1;
        int mid2;
        double l1;
        double l2;
        double r1;
        double r2;

        while (lo <= hi) {
            mid2 = (lo + hi) / 2;
            mid1 = len1 + len2 - mid2;

            l1 = (mid1 == 0) ? Integer.MIN_VALUE : nums1[(mid1 - 1) / 2];
            l2 = (mid2 == 0) ? Integer.MIN_VALUE : nums2[(mid2 - 1) / 2];

            r1 = (mid1 == len1 * 2) ? Integer.MAX_VALUE : nums1[mid1 / 2];
            r2 = (mid2 == len2 * 2) ? Integer.MAX_VALUE : nums2[mid2 / 2];

            if (l1 > r2) {
                lo = mid2 + 1;
            } else if (l2 > r1) {
                hi = mid2 - 1;
            } else {
                return (Math.max(l1, l2) + Math.min(r1, r2)) / 2;
            }
        }

        return -1;
    }
}
相关文章
相关标签/搜索