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)).
public class Solution {
private double median(int A[]){
int mid = A.length/2;
if(A.length%2 == 1)
return A[mid];
else
return ((double)A[mid-1] + (double)A[mid])/2;
}
public double findMedianSortedArrays(int A[], int B[]) {
// Start typing your Java solution below
// DO NOT write main() function
if(A == null || B == null)
return 0;
int midA = 0;
int midB = 0;
if(A.length == 0 && B.length == 0)
return 0;
if(A.length == 0)
return median(B);
if(B.length == 0)
return median(A);
int cut = 0;
while(true){
if(A.length <= 2||B.length <=2){
int [] tmp = new int[A.length+B.length];
int ndxA=0;
int ndxB=0;
for(int i=0; i<tmp.length; i++){
if(ndxB==B.length || (ndxA<A.length && A[ndxA]<=B[ndxB])){
tmp[i]=A[ndxA];
ndxA++;
}
else{
tmp[i]=B[ndxB];
ndxB++;
}
}
return median(tmp);
}
midA = A.length/2;
midB = B.length/2;
if(A.length%2 == 0)
midA --;
if(B.length%2 == 0)
midB --;
cut = midA<=midB?midA:midB;
if(A[midA] == B[midB]){
if((A.length%2 ==0) && (B.length%2 ==0))
return ((double)A[midA] + (double)(A[midA+1]<B[midB+1]?A[midA+1]:B[midB+1]))/2;
else
return A[midA];
}
else if(A[midA] < B[midB]){
A = Arrays.copyOfRange(A, cut, A.length);
B = Arrays.copyOfRange(B, 0, B.length - cut);
}
else{
A = Arrays.copyOfRange(A, 0, A.length-cut);
B = Arrays.copyOfRange(B, cut, B.length);
}
}
}
}
Bugs encountered:
1. Median of {a,b,c,d} is (b+c)/2
2. (double) 5/2 to get 2.5 instead of 2.0
------------------------------------------------------------------------------------------------------------------------------------------
LL's solution:
public class Solution {
public static int[] merge(int A[],int B[]){
//NOTE: A[] len = 1 or 2
int lenA = A.length;
int lenB = B.length;
int[] C = new int[lenA+lenB];
int i = 0, j = 0;
while(i<lenA && j < lenB){
if(B[j]<A[i]){
C[i+j] = B[j];
j++;
}
else{
C[i+j] = A[i];
i++;
}
}
if(i==lenA){
while(j<lenB){
C[i+j] = B[j];
j++;
}
}
else{
while(i<lenA){
C[i+j] = A[i];
i++;
}
}
return C;
}
public static double getMedian(int B[]){
double median;
int lenB = B.length;
if(lenB==0)
return 0;
//B is even
if(lenB%2 == 0){
int mid1 = B[lenB/2-1];
int mid2 = B[lenB/2];
median = 1.0*(mid1+mid2)/2;
}
//B is odd
else{
int mid = B[(lenB-1)/2];
median = mid;
}
return median;
}
public static double findMedian(int A[], int B[]){
//NOTE: A[] len = 1 or 2
int lenB = B.length;
int lenA = A.length;
double median;
if(lenB==0)
return getMedian(A);
return getMedian(merge(A,B));
}
public static double findMedianSortedArrays(int A[], int B[]) {
// Start typing your Java solution below
// DO NOT write main() function
int lenA = A.length;
int lenB = B.length;
double median;
if(lenA ==0 && lenB ==0)
return 0;
if(lenA <= 2){
median = findMedian(A,B);
return median;
}
if(lenB <= 2){
median = findMedian(B,A);
return median;
}
//shrink array if max and min in the same list
if(A[0]<B[0] && A[lenA-1]>B[lenB-1]){
int start = 0;
int end = lenA-1;
while(A[start]<B[0] && A[end]>B[lenB-1]){
start++;
end--;
}
A = Arrays.copyOfRange(A,start,end+1);
}
else if(B[0]<A[0] && B[lenB-1]>A[lenA-1]){
int start = 0;
int end = lenB-1;
while(B[start]<A[0] && B[end]>A[lenA-1]){
start++;
end--;
}
B = Arrays.copyOfRange(B,start,end+1);
}
//start bineary search
double midA = getMedian(A);
double midB = getMedian(B);
lenA = A.length;
lenB = B.length;
if(lenA==0)
return getMedian(B);
if(lenB==0)
return getMedian(A);
if(midA>midB){
//safe to remove last half of A, and first half of B
//But only remove len = short array/2
int len = (lenA<lenB)?lenA:lenB;
int cut;
//len is even
if(len%2 == 0)
cut = len/2-1;
//len is odd
else
cut = (len-1)/2;
A = Arrays.copyOfRange(A,0,lenA-cut);
B = Arrays.copyOfRange(B,cut,lenB);
median = findMedianSortedArrays(A,B);
}
else if(midA<midB){
//safe to remove last half of B, and first half of A
//But only remove len = short array/2
int len = (lenA<lenB)?lenA:lenB;
int cut;
//len is even
if(len%2 == 0)
cut = len/2-1;
//len is odd
else
cut = (len-1)/2;
B = Arrays.copyOfRange(B,0,lenB-cut);
A = Arrays.copyOfRange(A,cut,lenA);
median = findMedianSortedArrays(A,B);
}
else{
//midA = midB
median = midA;
}
return median;
}
}