[Leetcode题解] 4 Median of Two Sorted Arrays
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)).
题目传送门Median of Two Sorted Arrays
思路
抛开题目的时间复杂度要求不看,容易想到的是两种方法。第一种,将两个数组放在一起,然后排序,然后直接找到中位数,这种方法的时间复杂度是O(nlogn);另外一种方法是采用merge,直接找到第(m+n)/2个数即可,这种方法时间复杂度是O(n)。但是题目要求的是O(log(m+n))的复杂度,应该怎么办呢?
我最初的想法是,分别求出数组A, B的中位数a,b。当a < b
时,中位数肯定不会出现在A的前半段,B的后半段。因此去掉这两个半段,将剩下的数组继续求中位数,然后递归的进行判断。但是后来发现这种方法不可行,会将中位数丢弃掉的。
后来参考了网上的思路才醍醐灌顶。这道题目求中位数可以转化为求第k小的数(其中k = (m+n)/2
)。
方法是比较A[k/2-1]
与B[k/2-1]
:
1. 若A[k/2-1] < B[k/2-1]
,则A[0]
~A[k/2-1]
肯定都是A,B两个数组合并后的数组的前k小的数。也就是说A[k/2-1]
不可能大于A,B合并后的第k小的数。证明如下:假设A[k/2-1]
大于A,B合并后的第k小的数,不妨设A[K/2-1]
是第k+a
小的数(a是正整数),那么由于A[k/2-1] < B[k/2-1]
,那么假设B[k/2-1]
是第k+b
小的数(b>a
)。但是A数组中最多有k/2-1
个元素小于A[k/2-1]
,B数组中也最多有k/2-1
个元素小于A[k/2-1]
,那么合并后最多有k-2
个元素小于A[k/2-1],这与A[k/2-1]
是第k+a
小的数矛盾。因此我们可以将A[0]
~A[k/2-1]
抛弃,问题转化为在剩下的数据中找到第k-k/2
小的数。
2. 若A[k/2-1] > B[k/2-1]
,思路同上
3. 若A[k/2-1] < B[k/2-1]
,则找到第k小的数,返回结果。
解法
我的代码如下所示:
#define min(x, y) (((x)>(y))?(y):(x))
double find_the_kth(int * a, int m, int * b, int n, int k)
{
if(m > n)
{
return find_the_kth(b, n, a, m, k);
}
if(m == 0)
return b[k - 1];
if(k == 1)
return min(a[0], b[0]);
/* devide k into two parts */
int pa = min(k/2, m);
int pb = k - pa;
if(a[pa - 1] < b[pb - 1])
return find_the_kth(a + pa, m - pa, b, n, k - pa);
else if(a[pa - 1] > b[pb - 1])
return find_the_kth(a, m, b + pb, n - pb, k - pb);
else
return a[pa - 1];
}
double findMedianSortedArrays(int * nums1, int nums1Size, int * nums2, int nums2Size)
{
int total = nums1Size + nums2Size;
if(total & 0x01)
{
return find_the_kth(nums1, nums1Size, nums2, nums2Size, total/2 + 1);
}
else
{
return (find_the_kth(nums1, nums1Size, nums2, nums2Size, total/2)+
find_the_kth(nums1, nums1Size, nums2, nums2Size, total/2 + 1))/2;
}
}