LeetCode Find the median of two positively ordered arrays (4 questions)

LeetCode Find the median of two positively ordered arrays (4 questions)

@author: Jingdai
@date: 2021.03.14

Topic description (4 questions)

Given two sizes respectively mand nthe positive sequence (small to large) arrays nums1and nums2. Please identify and return these two positive sequence arrays median .

Idea and code

If you don’t consider the time complexity, you can easily think of two methods. One is to merge the arrays first, and then sort and find the median. The time complexity is O((m+n)*log(m+n) ) ; The other is to merge according to the order of the arrays. After the merge is an ordered array, the time complexity is O(m+n) to find the median . These two easy-to-think methods are not recorded here.

Insert picture description here

As shown, for nums1and nums2our aim is to find a dividing line, such that the elements are smaller than the left boundary element to the right of the dividing line, since an array sorted, so we only need to ensure that the elements on the boundary crossing to meet the requirements That is, nums1[i-1] <= nums2[j] and nums2[j-1] <= nums1[i] are satisfied.

We first calculate the total length of the two arrays len, then that is the number of elements in addition to the length of each side of the 2, where attention when lenis even, both sides of the elements are equal, lenis an odd number, while there will be one more element, and here I make the right choice one more element, therefore len/2always boundary number of elements on the left. At the same time, can be found in Figure subscripts iand superscripts jmay also represent a number of elements which correspond to the left of the array, i.e., it can be drawn I + J = len / 2 .

Then there is the core of the algorithm, because the array is sorted, you can use binary search to find the dividing line, we chose the shorter length of the array as nums1(if nums1the length is longer can make in the very beginning nums1and nums2exchange), then our goal is to use binary search to find the index iof the position. Here choose a shorter nums1binary search has two advantages, first and most immediate benefit is the low time complexity, there is a benefit is to choose nums1binary search can ensure that nums2the dividing line must have a corresponding, does not appear unable to trim both sides The situation of the element.

Insert picture description here

As shown above, if you select nums2an array as a binary search, as jwhen the position illustrated, it iwill not be found in the array so that the right side of the right dividing line dividing line four elements, left three elements, then have to write extra code for determining jthe position of the legality, also increases the complexity of the coding, so to select a shorter nums1array as binary search.

The situation discussed above is a general situation, but there are special situations. Look at the following two examples.

Example 1:

Insert picture description here

Example 2:

Insert picture description here

The above are only two examples, can be deduced i, i-1, jand j-1are likely to exceed the boundaries of the array, requiring special handling, as iequals nums1while the length of the nums[i]value Integer.MAX_VALUE , when iequal to 0, so that nums[i-1]the The value is Integer.MIN_VALUE ; the jsame is true , depending on the code.

Finally, a special case can be seen from the above, ithe value of [0, nums1.length] satisfy all the requirements, so that the initial values of the right nums1length, rather than nums1the length of -1.

The reference code is as follows:

public double findMedianSortedArrays(int[] nums1, int[] nums2) {
    
    
    if (nums1.length > nums2.length) {
    
    
        int[] temp = nums2;
        nums2 = nums1;
        nums1 = temp;
    }
    int len1 = nums1.length;
    int len2 = nums2.length;
    int len = len1 + len2;
    int halfLen = len / 2; // left count
    int left = 0;
    int right = len1;
    while (left < right) {
    
    
        int i = (left + right) / 2;
        int j = halfLen - i;
        /**
         ** s1 nums1[i-1] ------ s2 nums1[i]
         ** s3 nums2[j-1] ------ s4 nums2[j]
         **/
        int s1 = i-1 < 0 ? Integer.MIN_VALUE : nums1[i-1];
        int s2 = i == len1 ? Integer.MAX_VALUE : nums1[i];
        int s3 = j-1 < 0 ? Integer.MIN_VALUE : nums2[j-1];
        int s4 = j == len2 ? Integer.MAX_VALUE : nums2[j];
        if (s1 <= s4 && s3 <= s2) {
    
    
            left = i;
            break;
        } else if (s1 <= s4) {
    
    
            // s3 > s2
            left = i + 1;
        } else {
    
    
            right = i-1;
        }
    }

    int s1 = left-1 < 0 ? Integer.MIN_VALUE : nums1[left-1];
    int s2 = left == len1 ? Integer.MAX_VALUE : nums1[left];
    int s3 = halfLen-left-1 < 0 ? Integer.MIN_VALUE : nums2[halfLen-left-1];
    int s4 = halfLen-left == len2 ? Integer.MAX_VALUE : nums2[halfLen-left];

    if (len % 2 == 0) {
    
    
        return (double) (Math.min(s2, s4) + Math.max(s1, s3)) / 2.0;
    } else {
    
    
        return (double) Math.min(s2, s4);
    }
}

Guess you like

Origin blog.csdn.net/qq_41512783/article/details/114804567