[LeetCode] 4. Median of Two Sorted Arrays


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

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

</br>

Solution

The objective of the problem is to find the median of the combination of two sorted arrays, therefore the most obvious way to solve this problem is to first combine these two sorted arrays and then decide which is the median of the new array.

However, this method may lack in efficiency for we will waste time on re-sorting the array. We need something better than this. The goal is to find median under O(log (m+n)) time so we cannot simply insert the element from array B into array A; instead, we should try to achieve this in one pass.

Hence, the solution can be established.

Firstly, consider how to determine a median of an array: median is the number at the middle position of a sorted array. Hence, we only have to find the middle element of the combination of two array. Instead of re-sorting two arrays, we can divide both sorted arrays into two parts, as nums1[0,i],nums1[i,m],nums2[0,j]and nums2[j,n] and then put nums1[0,i] and nums2[0,j] in one set, nums1[i,m] and nums2[j,n] into another.

        Left_set         |          Right_set
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]

As two arrays are sorted, we only have to achieve requirements below in order to find the right median.
[a]. The maximum of the left_set is smaller than the minimum of the right_set;
[b]. The size of the left_size and right_set should be the same.

If the above the requirements is achieved, then we simply have to compute the median by median = (max(left_part) + min(right_part))/2.

Then, the next issue we have to deal with is how to make sure the requirement is met. Then, to ensure these two conditions, we just need to ensure:

(1)   i + j == m - i + n - j  (or: m - i + n - j + 1)
(2)   B[j-1] <= A[i] && A[i-1] <= B[j]

Therefore, we can have following steps.

[1] Set min = 0, max = m; then the search range is [min, max].

[2] Set i = (min + max)/2, j = (m + n + 1)/2 - i. 
     //By setting the value of i and j in this way, 
     //we can make sure the length of both set is equal.

[3] There are only 3 situations to deal with:
    <a> B[j-1] <= A[i] and A[i-1] <= B[j]
        Indicates the right `i`, return median;

    <b> B[j-1] > A[i]
        Indicates A[i] is too small. 
        We must adjust i to get B[j-1] <= A[i], hence we must increase i.
        By adjusting the search range to [i+1, max], B[j-1] is decreased and A[i] is increased, and B[j-1] <= A[i] may be satisfied.
        So, set min = i+1, and goto <2>.

    <c> A[i-1] > B[j]
        Indicates A[i-1] is too big. And we must decrease i to achieve A[i-1]<=B[j].
        So we must adjust the search range to [min, i-1].
        Set max = i-1, and goto <2>.

By adjusting the value of i and j, we can find where is the right place to divide two arrays.

When the right i is found, the median should be:

(when m + n is odd)
      max(A[i-1], B[j-1]) ;
(when m + n is even)
      (max(A[i-1], B[j-1]) + min(A[i], B[j]))/2 ;

The code is shown as below:
Java

public class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        
        int m = nums1.length, n = nums2.length;
        int max_of_left = 0, min_of_right = 0;
        
        if (m > n){
            int[] temp = nums1;
            nums1 = nums2;
            nums2 = temp;
            int temp_num = m;
            m = n;
            n = temp_num;
        }
    
        int min = 0, max = m, mid = (m + n + 1) / 2;
        
        while (min <= max){
            int i = (min + max) / 2;
            int j = mid - i;
            
            if (i < m && nums2[j-1] > nums1[i])
                // i is too small
                min = i + 1;
            else if (i > 0 && nums1[i-1] > nums2[j])
                // i is too big
                max = i - 1;
            else{
                // i is perfect
                if (i == 0) 
                    max_of_left = nums2[j-1];
                else if (j == 0)
                    max_of_left = nums1[i-1];
                else
                    max_of_left = Math.max(nums1[i-1], nums2[j-1]);
    
                if ((m + n) % 2 == 1)
                    return max_of_left;
    
                if (i == m) 
                    min_of_right = nums2[j];
                else if (j == n)
                    min_of_right = nums1[i];
                else 
                    min_of_right = Math.min(nums1[i], nums2[j]);
    
                return (max_of_left + min_of_right) / 2.0;
            }
        }    
        return 0;
    }
}

</br>

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 青春年少,難免會有叛逆萌發的沖動,細數過往便以長大,時光數栽,我們臨近而立之年,不曾想過還有多少青春值得留念,...
    踏過青春那條河閱讀 157評論 0 0
  • 夜近了,天暗了。 我翻了翻書桌上嶄新的書本,拿起了又放下。電腦屏幕打開的光把我的臉打的彤紅,手機不停地閃過扣扣信息...
    朝夕駿閱讀 103評論 0 0
  • 前幾天,語文節到了,我們進行了一次語文節的考試,里面考的題目五花八門,有看圖猜成語,有看拼音寫詞語,還有古詩詞...
    黎天曜閱讀 239評論 2 2
  • Singleton pattern 限定類對象只有一個實例核心原理是將構造函數私有化,并且通過靜態方法獲取一個唯一...
    wangdy12閱讀 182評論 0 0