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)).
1.merge O(n+m)
2.kth smallest of sorted array
不是一般性,认为数组a的长度m大于数组b的长度n,假设需要找到第k大的数,
if (m < n) return kth(b,n,a,m,k);
三种边界情况
if (n==0) return a[k-1]; if (k==1) return min(a[0],b[0]); if (k==m+n) return (a[m - 1] > b[n - 1])?a[m - 1]:b[n - 1];其他:
从B数组入手,因为B数组有序,我们尝试用二分法进行;取B[j], j = min(n,k/2), 对于数组A中,取A[i] i = k -j;//(i+j)=k;
如果说A[i-1] > B[j-1]时 ,那么比A[i-1]小的数至少有A中的 i-1个 和B中的 j个,又因为 i+j =k;所以第k小的数不可能是A[i-1]后面的数A[i] .....A[m-1](因为至少大于A[0].....A[i-1]和B[0].....B[j-1]共K个数),也不可能是B[j-1]前面的数B[0].....B[j-2](因为最多大于A[0].....A[i-2]和B[0]......B[j-2]共k-2个数,所以不可能为第k小的数);
所以第k小的数只能是在A[0].....A[i-1]以及B[j]......B[n-1]之中,此时在这之中需要找第 k -j小的数,因为已经扔掉了 B[0]....B[j-1] j个前k小的数。
如果说A[i-1] < B[j-1]时 ,那么比B[j-1]小的数至少有A中的 i个 和B中的 j-1个(A[0].....A[i-1]和B[0]....B[j-2]),又因为 i+j =k;所以第k小的数不可能是B[j-1]后面的数B[j] .....B[n-1](因为至少大于A[0].....A[i-1]和B[0].....B[j-1]共K个数),也不可能是A[i-1]前面的数A[0].....A[i-2](因为最多大于A[0].....A[i-2]和B[0]......B[j-2]共k-2个数,所以不可能为第k小的数);
所以第k小的数只能是在B[0].....B[j-1]以及A[i]......A[m-1]之中,此时在这之中需要找第 k -i小的数,因为已经扔掉了 A[0]....A[i-1] j个前k小的数。
具体实现如下:
class Solution { public: int kth(int a[], int m, int b[], int n, int k) { if (m < n) return kth(b,n,a,m,k); if (n==0) return a[k-1]; if (k==1) return min(a[0],b[0]); if (k==m+n) return (a[m - 1] > b[n - 1])?a[m - 1]:b[n - 1]; int j = min(n,k/2); int i = k-j; if (a[i-1] > b[j-1]) return kth(a,i,b+j,n-j,k-j); return kth(a+i,m-i,b,j,k-i); } double findMedianSortedArrays(int a[], int m, int b[], int n) { int k = (m+n)/2; int m1 = kth(a,m,b,n,k+1); if ((m+n)%2==0) { int m2 = kth(a,m,b,n,k); return ((double)m1+m2)/2.0; } return m1; } };
用vector实现:
class Solution { public: double findMedianSortedArrays(vector<int>& nums1, vector<int>& nums2) { int m = nums1.size(); int n = nums2.size(); int k = (m+n)/2; int m1 = kth(nums1,0,m-1,nums2,0,n-1,k+1); if ((m+n)%2==0) { int m2 = kth(nums1,0,m-1,nums2,0,n-1,k); return ((double)m1+m2)/2.0; } return m1; } int kth(vector<int> a,int al, int ar, vector<int> b, int bl, int br,int k) { if(ar - al <0 ) return b[bl+k-1]; if(br - bl <0 ) return a[al+k-1]; int m = ar - al + 1; int n = br - bl + 1; if (m < n) return kth(b,bl,br,a,al,ar,k); if (n==0) return a[k-1]; if (k==1) return min(a[al],b[bl]); if (k==m+n) return (a[ar] > b[br])?a[ar]:b[br]; int j = min(n,k/2); int i = k-j; if (a[i-1 + al] == b[j-1 + bl]) return a[i-1 + al]; if (a[i-1 + al] > b[j-1 + bl]) return kth(a,al,i-1+al,b,j+bl,br,k-j); return kth(a,al+i,ar,b,bl,j-1+bl,k-i); } };