数组中查找中位数
1、将两个数组合合并并排序,查找中位数,时间复杂度为O((n+m)lg(m+n)),空间复杂度O(m+n)。
2、分别比较两个数组的K/2处的数,如果midA < midB,说明要查找的两个数在数组A的右半部分和数组B的左半部份。如果midA>midB,说明要查找的两个数在数组A的左半部分和数组B的右半部份。每次比较丢掉一半,时间复杂度为O(lg(m+n)),空间复杂度为O(1)。以上说的半部分指的是K个值的半部分。
public static double getMid(int []A,int []B){
int l=(A.length+B.length+1)/2;
int r=(A.length+B.length+2)/2;
return (getMid(A,0,B,0,l)+getMid(A,0,B,0,r))/2.0;
}
public static int getMid(int[]A,int startA,int[]B,int startB,int k){
if(startA>A.length-1)return B[startB+k-1];
if(startB>B.length-1)return A[startA+k-1];
if(k==1)return Math.min(A[startA], B[startB]);
int midA=Integer.MAX_VALUE;
int midB=Integer.MAX_VALUE;
if(startA+k/2-1<A.length)midA=A[startA+k/2-1];
if(startB+k/2-1<B.length)midB=B[startB+k/2-1];
if(midA<midB){
//说明在A的右边的块,B的左边的块
return getMid(A,startA+k/2,B,startB,k-k/2);
}else if(midA>midB){
//说明在A的左边的块,B的右边的块
return getMid(A,startA,B,startB+k/2,k-k/2);
}else{
return midA;
}
}
数组中查找第K小的值
1、将两个数组合合并并排序,查找中位数,时间复杂度为O((n+m)lg(m+n)),空间复杂度O(m+n)。
2、分别比较两个数组的中位数,如果midA < midB且两个数组一半的长度和midVal小于等于K,说明要查找的数肯定不在B数组的右半部分。如果midA < midB且两个数组一半的长度和midVal大于K,说明要查找的数肯定不在A数组的左半部分。如果midA>midB且两个数组一半的长度和midVal小于等于K,说明要查找的数肯定不在A数组的右半部分。如果midA>midB且两个数组一半的长度和midVal大于K,说明要查找的数肯定不在B数组的左半部分。每次比较丢掉A的一半或者B的一半,时间复杂度大于O(lg(m+n))小于O(n),空间复杂度为O(1)。
public static int getKMin(int[] A, int[] B, int k) {
return getKMin(A, 0, A.length - 1, B, 0, B.length, k);
}
public static int getKMin(int[] A, int startA, int endA, int[] B,
int startB, int endB, int k) {
if (startA > endA)
return B[startB + k - 1];
if (startB > endB)
return A[startA + k - 1];
int midA = startA + (endA - startA) / 2;
int midB = startB + (endB - startB) / 2;
int midVal = midA - startA + midB - startB + 2;
if (A[midA] <= B[midB]) {
// 丢弃A的左半块
if (midVal <= k) {
return getKMin(A, midA + 1, endA, B, startB, endB, k
- (midA - startA + 1));
} else {
// 丢弃B的右半块
return getKMin(A, startA, endA, B, startB, midB - 1, k);
}
} else {
if (midVal <= k) {
// 丢弃B的左半块
return getKMin(A, startA, endA, B, midB + 1, endB, k
- (midB - startB + 1));
} else {
// 丢弃A的右半块
return getKMin(A, startA, midA - 1, B, startB, endB, k);
}
}
}
第一种方法每次丢弃A和B的K个值的一半,第二种方法每次丢掉A或B的一半,因此第一种方法比较好。