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)).
This problem can be transformed in another problem. Find the kth large element in the union set of two arrays, because the median is the middle element which is also a kth element.
Suppose we have two arrays, A[0...m−1] and B[0...n−1] with the size of m and
m and
n are even and m>=k/2 and n>=k/2
We define the kth element in union set ofA and B isx
So, A[k/2−1] and B[k/2−1] represent the k/2th elements in A and
Conclusion 1: If A[k/2−1]<B[k/2−1] , the {a
≤A[k/2−1] } are all smaller than x, wherea∈A .
The same with the situation A[k/2−1]>B[k/2−1]
From the Conclusion 1 we can directly remove the elements smaller than A[k/2−1] from A, because
We should also consider the edge case, that is, when should we stop?
- When A or B is empty, we return B[k-1]( or A[k-1]), respectively;
- When k is 1(when A and B are both not empty), we return the smaller one of A[0] and B[0]
- When A[k/2-1] = B[k/2-1], we should return one of them
public class Soluction4 {
public static int findKth(int[] a, int[] b, int k){//ah and bh represent the position of the first element(head) in a and b
int m = a.length;
int n = b.length;
//always assume that m is equal or smaller than n
if(m > n) return findKth(b , a , k);
if(m == 0) return b[k-1];
if(k == 1) return Math.min(a[0], b[0]);
//Find the index of A and B
int pa = Math.min(k/2, m);
int pb = k - pa;
if(a[pa-1] < b[pb-1]) return findKth(Arrays.copyOfRange(a, pa, m), b, k-pa);
else if (a[pa-1] > b[pb-1]) return findKth(a, Arrays.copyOfRange(b, pb, n), k-pb);
else return a[pa-1];
}
public static double findMedianSortedArrays(int[] nums1, int[] nums2) {
int total = nums1.length + nums2.length;
if(total % 2 == 0){
return ((double)findKth(nums1, nums2, total/2) + (double)findKth(nums1, nums2, total/2+1))/2;
} else {
return (double)findKth(nums1, nums2, total/2+1);
}
}
public static void main(String[] args) {
int[] nums1 = {3};
int[] nums2 = {1,2,4};
System.out.println(findMedianSortedArrays(nums1, nums2));
}
}
After the theory, we need prove Conclusion1 and some other special situations, like if k is not even.
We can use contradiction to prove Conclusion 1.
Proof: Suppose x in {
a ≤A[k/2−1]} where a∈A. That means A[k/2−1]≥x, then B[k/2−1]>A[k/2−1]≥x, so x can be in the set of {a≤A[k/2−1] } ∪ {b<B[k/2−1]} where a∈A and b∈B, but there only k−1 elements in this subset (k−1 from B andk from A) which is impossible.
Following, I did not write the details, just give the way to calculate the size of the subset in contradiction.
If
k/2 in program is actually ⌊k/2⌋ or k/2−1/2. And k−(k/2−1/2)=k+1/2.
So, the index of A andB is k/2−3/2 and k/2−1/2.
If A[k/2−3/2]<B[k/2−1/2], use the contradiction like the proof above, the size of subset contains x is alsok−1 (k−1/2 from B andk−1/2 from A).
If m <
The index of A and
B is m−1 and k−m+1.
If A[m−1]<B[k−m+1], use contradiction, the size of subset constains x :k−1=(m−1)+(k−m) m−1 from A,k−m from B. The same asA[m−1]>B[k−m+1]