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小的数字为Nk,通过某种方式删减一些比Nk小的数字,假设删减的数字的个数为n,那么剩下的问题就是找到剩下的数字中第Nk-n小的数字,然后如此递归。那么如何删减一些数字呢,假设K=10,并且两个数组都是由小到大排列的,那么比较一下两个数组的最小的数字,就可以找到两个数组中最小的数字,那么这个最小的数字肯定是可以删减的。但是这样还不够过瘾,还可以再删除一点,比较一下两个数组的第二小的数字,比较小的那个数字就是在两个数组融合排序之后排2~3名的。同样如果比较两个数组中的第5小的数字,那么比较小的数字是在两个数组融合排序之后排5~9名的。比较第一个数组中的第3小和第二个数组中的第7小的数字呢,比较小的那个要么排7~9要么排3~9,总之不会超过10,那么比较小的数字在其对应的数组中比它小的数字的排名都不会超过10。思路就是这样的。上代码,写文章的时候发现这个程序还是有点欠缺的,因为题中并没有假设两个数组都是从小到大排列的,这个程序默认是从小到大排列的了。刚好leetcode的所有测试案例都是从小到大排列的,提交的时候没有发现。总之重点不在这里。
class Solution {
public:
double findMedianSortedArrays(int A[], int m, int B[], int n) {
// IMPORTANT: Please reset any member data you declared, as
// the same Solution instance will be reused for each test case.
if((m+n)%2==1) return findKth(A,m,B,n,(m+n)/2+1);
else return (findKth(A,m,B,n,(m+n)/2)+findKth(A,m,B,n,(m+n)/2+1))*1.0/2;
}
double findKth(int A[], int m, int B[], int n, int k) {
if(m==0) return B[k-1];
if(n==0) return A[k-1];
if(k==1) return A[0]>B[0]?B[0]:A[0];
if(k%2==0)
{
if(m<k/2)
{
if(A[m-1]<=B[k-m-1]) return B[k-m-1];
else return findKth(A,m,B+(k-m),n-k+m,m);
}
if(n<k/2)
{
if(B[n-1]<=A[k-n-1]) return A[k-n-1];
else return findKth(B,n,A+(k-n),m-k+n,n);
}
if(A[k/2-1]>B[k/2-1]) return findKth(A,m,B+k/2,n-k/2,k/2);
else if(A[k/2-1]<B[k/2-1]) return findKth(A+k/2,m-k/2,B,n,k/2);
else return A[k/2-1];
}
else
{
if(m<=k/2)
{
if(A[m-1]<=B[k-m-1]) return B[k-m-1];
else return findKth(A,m,B+(k-m),n-k+m,m);
}
if(n<=k/2)
{
if(B[n-1]<=A[k-n-1]) return A[k-n-1];
else return findKth(B,n,A+(k-n),m-k+n,n);
}
if(A[k/2-1]>B[k/2-1]) return findKth(A,m,B+k/2,n-k/2,k/2+1);
else if(A[k/2-1]<B[k/2-1]) return findKth(A+k/2,m-k/2,B,n,k/2+1);
else return A[k/2]>B[k/2]?B[k/2]:A[k/2];
}
}
};