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
m
andn
the positive sequence (small to large) arraysnums1
andnums2
. 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.
As shown, for nums1
and nums2
our 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 len
is even, both sides of the elements are equal, len
is an odd number, while there will be one more element, and here I make the right choice one more element, therefore len/2
always boundary number of elements on the left. At the same time, can be found in Figure subscripts i
and superscripts j
may 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 nums1
the length is longer can make in the very beginning nums1
and nums2
exchange), then our goal is to use binary search to find the index i
of the position. Here choose a shorter nums1
binary search has two advantages, first and most immediate benefit is the low time complexity, there is a benefit is to choose nums1
binary search can ensure that nums2
the dividing line must have a corresponding, does not appear unable to trim both sides The situation of the element.
As shown above, if you select nums2
an array as a binary search, as j
when the position illustrated, it i
will 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 j
the position of the legality, also increases the complexity of the coding, so to select a shorter nums1
array as binary search.
The situation discussed above is a general situation, but there are special situations. Look at the following two examples.
Example 1:
Example 2:
The above are only two examples, can be deduced i
, i-1
, j
and j-1
are likely to exceed the boundaries of the array, requiring special handling, as i
equals nums1
while the length of the nums[i]
value Integer.MAX_VALUE , when i
equal to 0, so that nums[i-1]
the The value is Integer.MIN_VALUE ; the j
same is true , depending on the code.
Finally, a special case can be seen from the above, i
the value of [0, nums1.length] satisfy all the requirements, so that the initial values of the right nums1
length, rather than nums1
the 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);
}
}