Give two positively ordered (from small to large) arrays nums1 and nums2 of sizes m and n, respectively. Please find and return the median of these two positive arrays.
The time complexity of the algorithm should be O(log (m+n)).
Example 1:
Input: nums1 = [1,3], nums2 = [2]
Output: 2.00000
Explanation: merge array = [1,2,3], median 2
Example 2:
Input: nums1 = [1,2], nums2 = [3,4]
Output: 2.50000
Explanation: merged array = [1,2,3,4], median (2 + 3) / 2 = 2.5
Example 3:
Input: nums1 = [0,0], nums2 = [0,0]
Output: 0.00000
Example 4:
Input: nums1 = [], nums2 = [1]
Output: 1.00000
Example 5:
Input: nums1 = [2], nums2 = []
Output: 2.00000
Related Topics
array
Binary search
Divide and conquer
Method 1
The first method I think of is also simple and rough. Directly merge the two arrays and take the median after sorting
class Solution { public double findMedianSortedArrays(int[] nums1, int[] nums2) { double median = 0; ArrayList<Integer> list = new ArrayList<>(); for (int i = 0; i < nums1.length; i++) { list.add(nums1[i]); } for (int i = 0; i < nums2.length; i++) { list.add(nums2[i]); } Collections.sort(list); int sumLength = nums1.length + nums2.length; int index = sumLength / 2; if (sumLength % 2 == 0) {//Even number median = (list.get(index) + list.get(index - 1)) / 2.0; }else { median = list.get(index); } return median; } }
This method is the simplest, but the time complexity finally reaches O(m+n)
Method 2
It is also a topic required by the topic. If the time complexity is required to be reduced to O(log(m+n)), then the dichotomy should be used
I've also heard of dichotomy before. At that time, I said that a section of wire is broken, and then how to quickly find the breakpoint: energize the wire, and then take the middle to see if you can receive the electrical signal. The end of receiving the dead signal is the breakpoint, which eliminates half of the wire distance... That's what I said, but it's suddenly called for you to use here. I don't know how to use it
Here is a quote from the explanation of the boss in LeetCode:
The topic is to find the median, which is actually a special case of finding the k-th decimal, and there is an algorithm for finding the k-th decimal. One traversal is equivalent to removing a value that cannot be the median, that is, excluding one by one. Because the sequence is orderly, in fact, we can eliminate half and half. Suppose we want to find the k-th decimal, we can exclude k/2 numbers in each cycle. Look at the next example.
Suppose we're looking for the seventh smallest number.
We compare the k/2 number of the two arrays. If K is an odd number, round it down. That is, compare the third number, 4 in the upper array and 3 in the lower array. If which is smaller, it means that the first k/2 numbers of the array are not the smallest number k, so they can be excluded. That is, the three numbers 1, 2 and 3 can't be the seventh smallest number. We can exclude it. Compare 1349 and 45678910 arrays as new arrays.
More generally, A[1], A[2], A[3], A[k/2]..., B[1], B[2], B[3], B[k/2]..., if A[k/2] < B[k/2], then A[1], A[2], A[3], A[k/2] cannot be the smallest number k.
In array A, there are k/2-1 numbers smaller than A[k/2]. In array B, B[k/2] is smaller than A[k/2]. Assuming that the numbers in front of B[k/2] are smaller than A[k/2], there are only k/2-1, so there are at most k/1-1+k/2-1=k-2 numbers smaller than A[k/2], so A[k/2] is the smallest number in k-1 at most. The number smaller than A[k/2] is less likely to be the number smaller than k, so they can be excluded.
The orange part indicates the number that has been removed.
Since we have excluded three numbers, that is, these three numbers must be at the top, we only need to find the number 7 - 3 = 4 in the two new arrays, that is, k = 4. At this time, the two arrays compare the second number, 3 < 5, so we can exclude 1 and 3 from the small array.
We also exclude two numbers, so now we can find the small number 4 - 2 = 2. At this time, compare the number k / 2 = 1 in the two arrays, and 4 = = 4. What should I do? Since the two numbers are equal, no matter which array we remove, we can do it. Because removing one will always keep one, so it has no effect. For unification, let's assume 4 > 4, so remove the 4 below.
Since another number is removed, we need to find the first smallest number at this time, so we only need to judge which is the smaller number of the first number in the two arrays, that is, 4.
So the seventh smallest number is 4.
We always take the number of k/2 for comparison. Sometimes we may encounter when the length of the array is less than k/2.
At this time, k / 2 is equal to 3, and the length of the upper array is 2. We can point the arrow to the end of it. In this case, since 2 < 3, the upper arrays 1 and 2 will be excluded. Cause the situation below.
Since the two elements are excluded, k = 5 at this time, and because the upper array is empty, we only need to return the fifth number of the lower array.
From the above, we can see that whether we find the odd number or the even number has no impact on our algorithm, and in the process of the algorithm, the value of k may change from odd to even, and eventually become 1, or because an array is empty, we can directly return the result.
Therefore, we adopt the idea of recursion. In order to prevent the length of the array from being less than k/2, we compare the numbers corresponding to min(k/2) and Len (array) each time, exclude the numbers of the smaller array, enter the two new arrays into recursion, and K should subtract the number of excluded numbers. Recursive exit is when k=1 or the length of one of the numbers is 0.
Upper Code:
class Solution { public double findMedianSortedArrays(int[] nums1, int[] nums2) { //1. In the case of merging odd and even numbers, take the 'median' of the two numbers regardless of odd or even numbers, and then / 2 /* For example, even 6 and odd 7 For even number 6: (6 + 1) / 2 = = 3, (6 + 2) / 2 = = 4, (third number + fourth number) / 2 is exactly the median of the array with length 6 For odd number 7: (7 + 1) / 2 = = 4, (7 + 2) / 2 = = 4, (fourth number + fourth number) / 2 is also the median of the array with length 7 */ int len1 = nums1.length; int len2 = nums2.length; int left = (len1 + len2 + 1) / 2; int right = (len1 + len2 + 2) / 2; return (dichotomy(nums1, 0, len1 - 1, nums2, 0, len2 - 1, left) + dichotomy(nums1, 0, len1 - 1, nums2, 0, len2 - 1, right)) * 0.5; } /** * @param nums1 Subarray 1 * @param nums2 Subarray 2 * @param k The smallest number of k * @return The value of the k-th smallest number to find */ public int dichotomy(int[] nums1, int start1,int end1, int[] nums2, int start2,int end2, int k) { int len1 = end1 - start1 + 1;//Calculates the remaining length of two arrays int len2 = end2 - start2 + 1; //Let the length of len1 be less than len2, so as to ensure that there is an empty array, which must be num1, reducing a few if //This recursive method of directly calling myself to change the parameter position is also learned. My first thought is to exchange the values of num1 and num2 if (len1>len2) return dichotomy(nums2, start2, end2, nums1, start1, end1, k); if (len1==0) return nums2[start2 + k - 1]; if (k==1) return Math.min(nums1[start1], nums2[start2]); //start either excludes all or only k/2 //And whoever is young will be excluded. The min function is cleverly used to replace the if structure int i = start1 + Math.min(len1, k / 2) - 1; int j = start2 + Math.min(len2, k / 2) - 1; //Judge the size of the index number after the start move, decide who to keep the move, and reduce the search range if (nums1[i] > nums2[j]) { return dichotomy(nums1, start1, end1, nums2, j + 1, end2, k - (j + 1 - start2)); } else { return dichotomy(nums1, i + 1, end1, nums2, start2, end2, k - (i + 1 - start1)); } } }
There are still many gaps between understanding the ideas and writing the code of the introduction. When I write by my own ability, I write a lot of if, and then there will be a lot of omissions. Then I write it with reference to the code of the boss. Also realize that they still have a long way to go
The boss seems to be good at unifying a variety of complex situations into a few situations as far as possible, such as the odd and even problems above, which benefit a lot.