BinaryTom

导航

算法——有序数组中值

题目描述

有两个已排序数组A、B,各自大小分别为m,n。找到两个已排序数组的中值。

解题思路

将整个集合分为两个等长的子集,使一边的值总是大于另一边。这道题,可以将A、B看作一个整体,然后划分为左右两部分L和R,并且满足max(L)<=min(R)

当总个数(m+n)位奇数时,结果为:max(L)

当总个数(m+n)为偶数时,结果为:max(L)+min(R)2

这样一来,问题简化为了寻找平分整个集合的方法,假设0<=i<=m,使用 i 将数组A分为A0~Ai-1和Ai~Am-1,因此想要将集合均分,则需要j=m+n+12,将数组B分为B0~Bj-1 和Bj~Bn-1,于是数组分为了如下两部分。

L R
A[0],A[1],…,A[i-1] A[i],A[i+1],…,A[m-1]
B[0],B[1],…,B[j-1] B[j],B[j+1],…,B[n-1]

于是题目转化为,寻找合适的 i,使得max(L)<min(R),于是我们可以使用二分法来查找i值,找到i值后,就可以求出结果了。

代码

    public static double findMedianSortedArrays (int[] a, int[] b) {
        //交换数组,保证m<n
        if (a.length > b.length) {
            int[] temp = a;
            a = b;b = temp;
        }
        int m = a.length, n = b.length;
        int iMin = 0, iMax = m, halfLength = (m+n+1)/2;
        while (iMin <= iMax) {
            int i = (iMin + iMax)/2;
            int j = halfLength - i;

            if (i < iMax && b[j-1] > a[i]) {//当前i值较小,增加iMin到i+1处
                iMin = i+1;
            }else if (i > iMin && a[i-1] > b[j]) {//当前i值较大,减小iMax到i-1处
                iMax = i-1;
            }else {
                int maxLeft = 0;
                if (i == 0) {
                    maxLeft = b[j-1];
                } else if (j == 0) {
                    maxLeft = a[i-1];
                } else {
                    maxLeft = Math.max(a[i-1], b[j-1]);
                }
                //总个数位奇数时,返回max(L)
                if ((m + n)%2==1) {
                    return maxLeft;
                }

                int minRight = 0;
                if (i == m) {
                    minRight = b[j];
                } else if (j == n) {
                    minRight = a[i];
                } else {
                    minRight = Math.min(a[i], b[j]);
                }
                return (maxLeft+minRight)/2.0;
            }
        }
        return 0;
    }

posted on 2018-03-06 09:13  BinaryTom  阅读(109)  评论(0编辑  收藏  举报