1. 程式人生 > >演算法——有序陣列中值

演算法——有序陣列中值

題目描述

有兩個已排序陣列A、B,各自大小分別為m,n。找到兩個已排序陣列的中值。

解題思路

將整個集合分為兩個等長的子集,使一邊的值總是大於另一邊。這道題,可以將A、B看作一個整體,然後劃分為左右兩部分L和R,並且滿足 m a x ( L )

<= m i n ( R )

當總個數(m+n)位奇數時,結果為: m a x (

L )

當總個數(m+n)為偶數時,結果為: m a x ( L )

+ m i n ( R ) 2

這樣一來,問題簡化為了尋找平分整個集合的方法,假設 0 <= i <= m ,使用 i 將陣列A分為A0~Ai-1和Ai~Am-1,因此想要將集合均分,則需要 j = m + n + 1 2 ,將陣列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 ,使得 m a x ( L ) < m i n ( 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;
    }