【LeetCode系列】有序數組的中位數 Median of Two Sorted Arrays

問題描述: 

解決方案: 

因爲題目中給出的是已排序的數組,因此將問題轉化爲求第 k 小的數,當兩個數組大小之和爲奇數時,找第 \frac{m+n}{2} + 1小的數;當兩數組之和爲偶數時,找中間兩個數之和除以2即可,中間兩個數分別爲第\frac{m+n}{2}\frac{m+n}{2}+1小的數。

假設找第k小的數需要在數組A中找p次,在數組B中找q次,則 p + q = k。k已知而p和q未知,因此目的就是通過二分k找到p。

A[start1 + p - 1]代表的含義是指數組A“前進”了p步,對應於數組B需要“前進”q步。

①若A[start1 + p - 1] = B[start2 + q - 1],意味着已經找到,第k個數 kth = A[start1 + p - 1] = B[start2 + q -1]。因爲A和B都是有序的,因此從A[start1]到A[start1 + p - 1](共p - 1 + 1個數)、B[start2]到B[start2 + q - 1](共q - 1 + 1個數)也是有序的,如果將這兩個子數組合併成一個數組則總共有 p - 1 + q - 1 + 2= k個數,而其中最大的數就是A[start1 + p - 1] = B[start2 + q - 1],即第k小的數(注意每個數組都是從小到大排序的,並不需要關心合併後的內部順序)。

②若A[start1 + p - 1] < B[start2 + q - 1],意味着數組A中A[start1 + p - 1]之前的數字全都小於B[start2 + q - 1](因爲數組A是從小到大排序的),因此第k小的數一定不會在數組A的前p個數中,因此我們可以把它捨棄以後進行遞歸操作,但遞歸時因爲我們捨棄了前面的p個數,因此下一步就是找第 k - p小的數了。

③若A[start1 + p - 1] > B[start2 + q - 1],與上面情況類似,捨棄數組B的前q個元素,遞歸找第 k - q 小的數。

 

class Solution {
    public double findMedianSortedArrays(int[] A, int[] B) {
        int m = A.length;
        int n = B.length;
        int total = m + n;
        if((total % 2) == 1){
            return findKthNumber(A, m, 0, B, n, 0, total / 2 + 1);    //找到第total/2+1小的數
        }else{
            return (findKthNumber(A, m, 0, B, n, 0, total / 2) + findKthNumber(A, m, 0, B, n, 0, total / 2 + 1)) / 2;
        }
    }
    
    public double findKthNumber(int[] A, int m, int start1, int[] B, int n, int start2, int k){
        //一定注意這三個if的順序
        if(m > n){    //保證A的長度一定小於B
            return findKthNumber(B, n, start2, A, m, start1, k);
        }
        if(m == 0){    //如果一個數組長度爲0,則只要直接返回另一個數組的第k個元素即可
            return B[start2 + k - 1];
        }
        if(k == 1){    //返回第1小的數只要比較當前A和B中最小的即可
            return Math.min(A[start1], B[start2]);
        }
        //第k小的數在數組A中找了p次,在數組B中找了q次,p + q = k
        //二分:實際上是二分k找p
        int p = Math.min(k/2, m);    //若p > m會越界, 因此返回兩者中的小值
        int q = k -p;
        if(A[start1 + p - 1] == B[start2 + q - 1]){    //說明已找到
            return A[start1 + p - 1];
        }else if(A[start1 + p - 1] < B[start2 + q - 1]){
            return findKthNumber(A, m - p, start1 + p, B, n, start2, k - p);
        }else{
            return findKthNumber(A, m, start1, B, n - q, start2 + q, k - q);
        }
    }
}

參考:

https://www.jianshu.com/p/9bd57fd52062

https://blog.csdn.net/yutianzuijin/article/details/11499917

https://leetcode.com/problems/median-of-two-sorted-arrays/solution/

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章