Median of Two Sorted Arrays-LeetCode
题目:
There are two sorted arrays A and B of size m and n respectively.Find the Median of two sorted arrays.The overall run time complexity should be O(log(m+n)).
题目分析:
当我第一眼看见这题目时,就想到采用归并排序的方式,在两个数组上设立两个指针从头开始逐一比较。直到找到对应的元素为止。下面是自己开始写的代码:
1 class Solution { 2 public: 3 4 double findMedianSortedArrays(int A[], int m, int B[], int n) { 5 double result,right; 6 int num=(n+m+1)/2; 7 int i=0,j=0,cnt=0; 8 9 while(i!=m && j!=n){ 10 if(A[i]<=B[j]){ 11 result=A[i]; 12 i++; 13 cnt++; 14 } 15 16 else{ 17 result=B[j]; 18 j++; 19 cnt++; 20 } 21 22 if(cnt==num) { 23 flag=true; 24 break; 25 } 26 } 27 28 while(i!=m){ 29 if(cnt==num) break; 30 else{ 31 result=A[i]; 32 i++; 33 cnt++; 34 } 35 } 36 37 while(j!=n){ 38 if(cnt==num) break; 39 else{ 40 result=B[j]; 41 j++; 42 cnt++; 43 } 44 } 45 46 return result; 47 }
但是运行之后就发现出现了错误,折腾了很久也没有想明白。后面在网上找资料,才明白自己犯了一个最基本的错误,没有理解Median的含义。当Array的个数是奇数时,Median的值是最中间的一个。当它是偶数时,Median的值是n/2和n/2+1上的值的平均数。
网上的解法普遍都是一样的,看了之后发现这种解法确实很巧妙,貌似是某年考研的算法题,先记录下来。
解题思路:
该方法的核心是将原问题转变成一个寻找第k小的数问题(假设两个原序列升序排列),这样中位数实际上是第(m+n)/2小的数(暂不考虑偶数情形).所以只要解决了第k小的数,原问题就得以解决。
首先假设数组A和B的元素个数都大于k/2,我们比较A[k/2-1]和B[k/2-1]两个元素,分别代表A和B数组的第k个元素。如果A[k/2-1]<B[k/2-1],这表示A[0]到A[k/2-1]的元素都在A和B合并之后的前k个元素中。也就是说,A[k/2-1]不可能大于两数组合并之后的第k小值,所以我们可以将其抛弃。(注意:这是该算法最核心的地方)。
反证法:
假设A[k/2-1]大于合并之后的第k小值,我们不妨假定为第(k+1)小值。由于A[k/2-1]小于B[k/2-1],所以B[k/2-1]至少是第(k+2)小值。但实际上,在A中至多存在k/2-1个元素小于A[k/2-1],B中至多存在k/2-1个元素A[k/2-1],所以小于A[k/2-1]的元素个数至多有k/2+k/2-2,小于k,这与A[k/2-1]是k+1的数矛盾。
当A[k/2-1]>B[k/2-1]时也类似。
当A[k/2-1]==B[k/2-1]时,则我们已经找到第k的元素,也就是这个相等的元素。将其记为m,由于A和B中分别有k/2-1个元素小于m,所以m即是第k小的数。
因此总结起来就是:
- 如果A或者B为空,则直接返回B[k-1]或者A[k-1]。
- 如果k为1,我们只需要返回A[0]和B[0]中的较小值。
- 如果A[k/2-1]=B[k/2-1],返回其中一个。
代码如下:
1 public:{ 2 3 dobule findKth(int A[],int m,int B[],int n,int k){ 4 //m is equal or smaller than n 5 if(m<n) 6 return findKth(B,n,A,m,k); 7 if(m==0) 8 return B[k-1]; 9 if(k==1) 10 return min(A[0],B[0]); 11 12 int pa=min(k/2,m),pb=k-pa; 13 if(A[pa-1]<B[pb-1]) 14 return findKth(A+pa,m-pa,B,n,k-pa); 15 else if(A[pa-1]>B[pb-1]) 16 return findKth(A,m,B+pb,n-pb,k-pb); 17 else 18 return A[pa-1]; 19 } 20 21 dobule findMedianSortedArrays(int A[],int m,int B[],int n){ 22 int k=m+n; 23 if(k & 0x1){ 24 return findKth(A,m,B,n,k/2+1); 25 } 26 else{ 27 return (findKth(A,m,B,n,k/2)+findKth(A,m,B,n,k/2+1))/2; 28 } 29 } 30 };