Median of Two Sorted Arrays

LeetCode # 4

Problem statement

Given two sorted arrays nums1 and nums2 of size m and n respectively, return the median of the two sorted arrays.

The overall run time complexity should be O(log (m+n)).

Example

Example 1:

Input: nums1 = [1,3], nums2 = [2]
Output: 2.00000
Explanation: merged array = [1,2,3] and median is 2.

Example 2:

Input: nums1 = [1,2], nums2 = [3,4]
Output: 2.50000
Explanation: merged array = [1,2,3,4] and median is (2 + 3) / 2 = 2.5.

JAVA CODE Median of Two Sorted Arrays

BRUTE FORCE APPROACH

LOGIC

  • Merge 2 arrays by traversing 2 given array in 3rd array i.e. result.
  • Find median from result array and return.
class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int length1 = nums1.length, length2 = nums2.length; 
        int[] result = new int[length1 + length2];
        double median = 0.0;

        int index1 = 0, index2 = 0, index3 = 0;
        while (index1 < length1 && index2 < length2) {
            if (nums1[index1] < nums2[index2]){
                result[index3] = nums1[index1];
                index1++;
                index3++;
            }else{
                result[index3] = nums2[index2];
                index2++;
                index3++;
            }
        }

        while (index1 < length1){
            result[index3] = nums1[index1];
            index1++;
            index3++;
        }

        while (index2 < length2){
            result[index3] = nums2[index2];
            index2++;
            index3++;
        }

        if ((length1 + length2) % 2 == 0){
            median = ((double)(result[index3/2]) + (double)(result[(index3/2)-1])) / (double)(2.0);
        } else {
            median = (double)(result[index3/2]);
        }

        return median;
    }
}

Better Approach

LOGIC

  • We need only 2 value median_value_1 and median_value_2 to find out median.
  • We DO NOT need to save entire 3rd result array.
  • We can keep track of counter while comparing in above brute force code, once it reaches (total/2) OR (total/2)-1 index value, we will save them.
  • Another thing, we can do, as soon as it reached total/2, we can break out of the loop and return median directly using median formula.
    • This will save execution time for rest of the total/2 numbers comparison.
class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {
        int length1 = nums1.length, length2 = nums2.length; 
        int total = length1 + length2;
        double median = 0.0;
        int median_value_1 = 0, median_value_2 = 0;
        int index1 = 0, index2 = 0, counter = 0;

        while (index1 < length1 && index2 < length2) {
            if (nums1[index1] < nums2[index2]){
                if (counter == total/2) {
                    median_value_1 = nums1[index1];
                }else if (counter == (total/2)-1){
                    median_value_2 = nums1[index1];
                }
                index1++;
                counter++;
            }else{
                if (counter == total/2) {
                    median_value_1 = nums2[index2];
                }else if (counter == (total/2)-1){
                    median_value_2 = nums2[index2];
                }
                index2++;
                counter++;
            }
        }

        while (index1 < length1){
            if (counter == total/2) {
                median_value_1 = nums1[index1];
            }else if (counter == (total/2)-1){
                median_value_2 = nums1[index1];
            }
            index1++;
            counter++;
        }

        while (index2 < length2){
            if (counter == total/2) {
                median_value_1 = nums2[index2];
            }else if (counter == (total/2)-1){
                median_value_2 = nums2[index2];
            }
            index2++;
            counter++;
        }

        if (total % 2 == 0){
            median = (median_value_1 + median_value_2) / (double)(2.0);
        } else {
            median = (double)(median_value_1);
        }

        return median;
    }
}

Optimal Solution

Logic

  • We have to divide small array such that there will 2 partition partitionX in smaller array & partitionY in bigger array.
  • Then we will check if all elements on the left hand side of partition are smaller than all elements on the right hand side both partition.
    • We can do this simply by checking below condition
    • (maxLeftX <= minRightY && maxLeftY <= minRightX)
    • maxLeftX is the maximum element on the left hand side & minRightX is the minimum element on the right hand side of smaller array.
    • similarly, we will define minRightY and maxLeftY for bigger array.
  • To handle edge case, we we are at the boundary, we will use Integer.MIN_VALUE and Integer.MAX_VALUE as -INFINITY, +INFINITY.

Complexity

  • Time Complexity : O(log(min(x,y)))
    • That log of number of elements in smaller array.
  • Space Complexity : O(1)
    • No extra space used.
class Solution {
    public double findMedianSortedArrays(int[] nums1, int[] nums2) {

        // 1. find smallest array
        if (nums1.length > nums2.length){
            return findMedianSortedArrays(nums2, nums1);
        }

        // 2. traverse over smaller array
        int x = nums1.length;
        int y = nums2.length;
        int maxLeftX, maxLeftY, minRightX, minRightY;

        int low = 0;
        int high = x;
        while (low <= high) {
            // partitionX + partitionY = (x + y + 1) / 2;
            int partitionX = (low + high) / 2;
            int partitionY = ((x + y + 1) / 2) - partitionX; 

            maxLeftX = (partitionX == 0) ? Integer.MIN_VALUE : nums1[partitionX-1];
            minRightX = (partitionX == x) ? Integer.MAX_VALUE: nums1[partitionX];

            maxLeftY = (partitionY == 0) ? Integer.MIN_VALUE : nums2[partitionY-1];
            minRightY = (partitionY == y) ? Integer.MAX_VALUE : nums2[partitionY];

            // 3. logic 
            if (maxLeftX <= minRightY && maxLeftY <= minRightX){
                if ((x+y) % 2 == 0){
                    return (Math.max(maxLeftX, maxLeftY) + Math.min(minRightX, minRightY)) / (double)(2.0);
                } else {
                    return (double)(Math.max(maxLeftX, maxLeftY));
                }
            } else if (maxLeftX > minRightY) {
                // shift towards left
                high = partitionY - 1;
            } else { 
                // shift towards right
                low = partitionX + 1;
            }
        }

        throw new IllegalArgumentException();
    }
}

Visit https: https://codeandalgo.com for more such contents.

Leave a Reply

Your email address will not be published. Required fields are marked *