There are two sorted arrays A and B 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)).
分析:找两个已排序数组的中位数,其实就是将两个有序数组有序合并后找第K小的数。而找第K小的数,可以将K平分到两个数组中,然后利用一个重要的结论:如果 A[k/2−1]<B[k/2−1] ,那么A[0]~A[k/2-1]一定在第k小的数的序列当中,可以用反证法证明。
findKth()函数思路如下:
1. 保持A是短的那一个数组,B是长的
2. 平分k, 一半在A,一半在B (如果A的长度不足K/2,那就pa就指到最后一个)
3. 如果pa的值 < pb的值,那证明第K个数肯定不会出现在pa之前,递归,把A数组pa之前的砍掉,同理递归砍B数组。
4. 递归到 m == 0 (短的数组用完了) 就返回 B[k - 1], 或者k == 1(找第一个数)就返回min(A第一个数,B第一个数)。
#include <iostream>
#include <vector>
using namespace std;
class Solution {
public:
//寻找第K大的元素
int findKth(int a[], int m, int b[], int n, int k)
{
if(m > n)
return findKth(b, n, a, m, k);
if(m == 0)
return b[k-1];
if(k == 1)
return min(a[0], b[0]);
int pa = min(k/2, m);
int pb = k-pa;
if(a[pa-1] < b[pb-1])
return findKth(a+pa, m-pa, b, n, k-pa);
else if(a[pa-1] > b[pb-1])
return findKth(a, m, b+pb, n-pb, k-pb);
else
return a[pa-1];
}
double findMedianSortedArrays(int a[], int m, int b[], int n)
{
int total = m+n;
if(total%2==0)
{
double p = findKth(a, m, b, n, total/2);
double q = findKth(a, m, b, n, total/2+1);
return (p+q)/2;
}
else
return findKth(a, m, b, n, total/2+1);
}
//利用排序将两个数组合并成一个数组,然后返回中位数
void findMedian(vector<int>& nums1, vector<int>& nums2)
{
vector<int> nums;
auto a = nums1.begin();
auto b = nums2.begin();
while(a!=nums1.end() && b!=nums2.end())
{
if(*a <= *b)
{
nums.push_back(*a);
a++;
}
else
{
nums.push_back(*b);
b++;
}
}
if(a==nums1.end() && b!=nums2.end())
{
while(b!=nums2.end())
{
nums.push_back(*b);
b++;
}
}
if(a!=nums1.end() && b==nums2.end())
{
while(a!=nums1.end())
{
nums.push_back(*a);
a++;
}
}
float result;
if(nums.size()%2==0)
result= ((float)nums[nums.size()/2-1]+nums[nums.size()/2])/2;
else
result = nums[nums.size()/2];
cout<<result<<endl;
}
};
int main()
{
Solution S;
int n1[] = {1, 2};
int n2[] = {3, 4, 5, 6};
double result = S.findMedianSortedArrays(n1, 2, n2, 4);
cout<<result<<endl;
return 0;
}