[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
  • 夜近了,天暗了。 我翻了翻书桌上崭新的书本,拿起了又放下。电脑屏幕打开的光把我的脸打的彤红,手机不停地闪过扣扣信息...
    朝夕骏阅读 105评论 0 0
  • 前几天,语文节到了,我们进行了一次语文节的考试,里面考的题目五花八门,有看图猜成语,有看拼音写词语,还有古诗词...
    黎天曜阅读 239评论 2 2
  • Singleton pattern 限定类对象只有一个实例核心原理是将构造函数私有化,并且通过静态方法获取一个唯一...
    wangdy12阅读 182评论 0 0