给定两个大小分别为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。请你找出并返回这两个正序数组的中位数 。
算法的时间复杂度应该为 O(log (m+n)) 。
输入:nums1 = [1,3], nums2 = [2]
输出:2.00000
解释:合并数组 = [1,2,3] ,中位数 2
输入:nums1 = [1,2], nums2 = [3,4]
输出:2.50000
解释:合并数组 = [1,2,3,4] ,中位数 (2 + 3) / 2 = 2.5
n u m s 1. l e n g t h = = m nums1.length == m nums1.length==m
n u m s 2. l e n g t h = = n nums2.length == n nums2.length==n
0 < = m < = 1000 0 <= m <= 1000 0<=m<=1000
0 < = n < = 1000 0 <= n <= 1000 0<=n<=1000
1 < = m + n < = 2000 1 <= m + n <= 2000 1<=m+n<=2000
− 1 0 6 < = n u m s 1 [ i ] , n u m s 2 [ i ] < = 1 0 6 -10^6 <= nums1[i], nums2[i] <= 10^6 −106<=nums1[i],nums2[i]<=106
数据量不大,可以直接合并数组,然后求中位数。
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
vector<int> nums3;
int i = 0, j = 0;
while (i < nums1.size() && j < nums2.size()){
if(nums1[i] < nums2[j])
nums3.push_back(nums1[i++]);
else
nums3.push_back(nums2[j++]);
}
while (i < nums1.size()){
nums3.push_back(nums1[i++]);
}
while (j < nums2.size()){
nums3.push_back(nums2[j++]);
}
return (nums3[(nums3.size() - 1)/ 2] + nums3[nums3.size() / 2]) / 2.0;
}
将中位数求解转换为求第k小的数,然后分奇偶讨论。
int findKthElement(vector<int>& nums1, vector<int>& nums2, int k){
int i = 0, j = 0;
while (i < nums1.size() && j < nums2.size()){
if(i + j + 1 == k){
return min(nums1[i], nums2[j]);
}
if(nums1[i] < nums2[j]) {
i++;
}else {
j++;
}
}
if(i < nums1.size()){
return nums1[k - nums2.size() - 1];
}else{
return nums2[k - nums1.size() - 1];
}
}
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int n = nums1.size() + nums2.size();
int a = findKthElement(nums1, nums2, (n + 1) / 2);
if(n % 2 == 1){
return a;
}
return (findKthElement(nums1, nums2, n / 2 + 1) + a) / 2.0;
}
每次排除 k / 2 个数,指导一个数组为空,或者 k = 1
int findKthElement(vector<int>& nums1, vector<int>& nums2, int k){
int n = nums1.size(), m = nums2.size();
int offset1 = 0;
int offset2 = 0;
while (1){
if(offset1 == n) return nums2[offset2 + k - 1];
if(offset2 == m) return nums1[offset1 + k - 1];
if(k == 1) return min(nums1[offset1], nums2[offset2]);
int x = k / 2 - 1;
int newoffset1 = min(n - 1, offset1 + x);
int newoffset2 = min(m - 1, offset2 + x);
if(nums1[newoffset1] < nums2[newoffset2]){
k -= newoffset1 + 1 - offset1;
offset1 = newoffset1 + 1;
}else{
k -= newoffset2 + 1 - offset2;
offset2 = newoffset2 + 1;
};
}
}