1. 在统计中,中位数被用来:
将一个集合划分为两个长度相等的子集,其中一个子集中的元素总是大于另一个子集中的元素。
2. 解法1
简单粗暴,先将两个数组合并,两个有序数组的合并也是归并排序中的一部分。然后根据奇数,还是偶数,返回中位数。
class Solution {
public:
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int m = nums1.size(), n = nums2.size();
vector<int> num(m+n);
int s1=0, s2=0, k=0;
while(s1!=m && s2!=n) {
if(nums1[s1]<=nums2[s2]) num[k++] = nums1[s1++];
else num[k++] = nums2[s2++];
}
while(s1!=m) {
num[k++] = nums1[s1++];
}
while(s2!=n) {
num[k++] = nums2[s2++];
}
if(((m+n)&1)==0) return (num[(m+n)/2]+num[(m+n)/2-1])/2.0;
else return num[(m+n)/2]*1.0;
}
};
时间复杂度:遍历全部数组 (m+n)
空间复杂度:开辟了一个数组,保存合并后的两个数组 O(m+n)
3. 解法二
1. 其实,我们不需要将两个数组真的合并,我们只需要找到中位数在哪里就可以了。
2. 题目是求中位数,其实就是求第 k
小数的一种特殊情况,而求第 k
小数有一种算法。
class Solution {
public:
int getK(vector<int>& nums1,int s1,int e1,vector<int>& nums2,int s2,int e2,int k) {
int len1 = e1-s1+1, len2 = e2-s2+1;
if(len1>len2) return getK(nums2,s2,e2,nums1,s1,e1,k);
if(len1==0) return nums2[s2+k-1];
if(k==1) return nums1[s1]>nums2[s2] ? nums2[s2]:nums1[s1];
int i = s1+min(len1,k/2)-1;
int j = s2+min(len2,k/2)-1;
if(nums1[i]>nums2[j]) return getK(nums1,s1,e1,nums2,j+1,e2,k-(j-s2+1));
else return getK(nums1,i+1,e1,nums2,s2,e2,k-(i-s1+1));
}
double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) {
int m = nums1.size(), n = nums2.size();
int left = (m+n+1)/2;
int right = (m+n+2)/2;
return (getK(nums1,0,m-1,nums2,0,n-1,left) +
getK(nums1,0,m-1,nums2,0,n-1,right))/2.0;
}
};
时间复杂度:每进行一次循环,我们就减少 k/2 个元素,所以时间复杂度是 O(log(k),而 k=(m+n)/2,所以最终的复杂也就是 O(log(m+n))。
空间复杂度:虽然我们用到了递归,但是可以看到这个递归属于尾递归,所以编译器不需要不停地堆栈,所以空间复杂度为 O(1)。