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
Solving problems
Time complexity: O (log (min (m + n))
Eye:
1. Sorted when two arrays
2. The time complexity of the solution is less than O(log(m+n). (The following ideas outweigh this complexity)
From the point of view of the question, look up in dichotomy.
Median
Our aim is to find such a number. A set of numbers can be divided into two subsets of equal length, so that the number of one subset is less than that of the other.
Train of thought:
- Define a small subset as left_part and a large subset as right_part. What we need to do is to receive two arrays nums1 and nums2, part of the smaller number to left_part, the remaining large number to right_part. It is also necessary to ensure that the two subsets are equal in length (excluding the median itself). Nums1 is divided into i and nums2 is divided into j, as follows:
nums1[0], ..., nums1[i -1] | nums1[i], ..., nums1[m] nums2[0], ..., nums2[j -1] | nums2[j], ..., nums2[n]
Mathematical expression that satisfies the partition described above:
// 1. Number on the left = Number on the right i + j = (m - i) + (n - j); // The case where the median is not in the array, i.e. (m + n)% 2 = 0. i + j = (m - i) + (n - j) + 1; // The median itself exists in two arrays, i.e. (m + n)% 2!= 0. // We agreed to divide the median into left_part. // 2. All left_parts are less than or equal to right_part s, because nums1 and nums2 are sorted and do not need to be compared with their own elements. nums2[j - 1] < nums1[i] && nums1[i - 1] < nums2[j]
- After such a division is made, the median is easy to find. In the even case, the median is the mean of the maximum in left_part and the minimum in right_part. In odd cases, the median is the largest in left_part (because we agreed to assign it to left_part)
median = (max(nums1[i - 1], nums2[j - 1]) + max(nums1[i] + nums2[j])) / 2; // (m + n) % 2 = 0 median = max(nums1[i - 1], nums2[j - 1]) // (m + n) % 2 != 0
- From the equation in 1, we find that for deterministic i, j is also uniquely determined. For the two cases, there are:
j = (m + n) / 2 - i; j = (m + n + 1) / 2 - i; // (m + n) % 2 != 0
In fact, you only need to use the second expression, because in even cases, 1/2 will not work, decimal parts in the code will be forced to reduce the whole.
- Therefore, this problem has turned into the dichotomy problem of finding an appropriate i in the interval [0, m]. The algorithm is described as follows:
1. Find an i = nums[mid] in the interval [left, right] (initially, left = 0, right = m) dichotomy. Corresponding J = m + N + 1 / 2 - I. 2. Check the size relationship between left_part and right_part median: a. nums2[j - 1] < nums1[i] && nums1[i - 1] < nums2[j] i meet the requirements, stop searching, jump to 3. b. nums2[j - 1] > nums1[i] i is small, adjust the search scope to [mid, right], return 1 to execute. c. nums1[i - 1] > nums2[j] i is larger, adjust the search scope to [left, mid], return 1 to execute. 3. Calculate the median of return. The second part of the reference train of thought.
- These are the main ideas and steps. Next, we need to consider some special situations.
a. Boundary problems. In other words, i = 0,j = 0, i = n, j =m may occur, making nums1[i - 1],nums2[j - 1],nums1[i],nums[j] cross the boundary. These four cases respectively indicate that nums1 and nums2 are all divided into right_part, nums1 and nums2 are all divided into left_part. Having made this clear, it will be handled very well.
For example, when i = 0, nums1 has been partitioned into right_part, it is not necessary to judge nums1 [i-1] < nums2 [j] (the original purpose of our judgment is to ensure left_part < right_part). When calculating the median, the largest part of left_part must be nums2 [j-1], without considering nums [i-1], and the other same.
b. left_part and right_part boundary number duplication problems. That is to say, the maximum number in left_part is the same as the minimum number in right_part, which is also a good solution. In this case, the median is the boundary repetition number, which can be divided into the stopping conditions.
To sum up a and b, the judgment condition in step 2 of step 4 is changed to the following: uuuuuuuuuuu
(i == 0 || j == n || nums1[i - 1] <= nums2[j]) && (j == 0 || i == m || nums2[j - 1] <= nums1[i])
Source of problem solving
#include<iostream> #include<vector> #include<algorithm> using namespace std; class Solution { public: double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) { int m = nums1.size(), n = nums2.size(); if (m > n) return findMedianSortedArrays(nums2, nums1); int left = 0, right = m; int i = -1, j = -1; // Find the right i while (true) { i = (left + right) / 2; j = (m + n + 1) / 2 - i; if ((i == 0 || j == n || nums1[i - 1] <= nums2[j]) && (j == 0 || i == m || nums2[j - 1] <= nums1[i])) { break; } else if (i > 0 && nums1[i - 1] > nums2[j]) { right = i - 1; } else if (j > 0 && nums2[j - 1] > nums1[i]) { left = i + 1; } } // Calculate median int max_left = -1, min_right = -1; if (i == 0) max_left = nums2[j - 1];// If I = 0, the largest part of left_part must be nums2[j - 1], without considering nums1[i - 1] else if (j == 0) max_left = nums1[i - 1]; else { max_left = max(nums1[i - 1], nums2[j - 1]); } if ((m + n) % 2) { return max_left;// The values of i,j conform to this convention: in odd cases, the median is assigned to left_part } if (i == m) min_right = nums2[j]; else if (j == n) min_right = nums1[i]; else { min_right = min(nums1[i], nums2[j]); } return double(max_left + min_right) / 2; } };