我遵循中位数比较算法来查找两个已排序数组的中位数并在java中实现。根据算法时间复杂度是O(lgn),但由于它涉及创建子数组(方法createSubArr),我认为根据我的代码,它是O(n)。以下是我实施的代码。
class Median
{
public static void main (String[] args)
{
int[] a = {1,12,15,26,38,40};
int[] b = {2,13,17,30,45,50};
System.out.println(getMedian(a,b,6));
}
private static int median(int[] a, int n){
if(n % 2 == 0) return (a[n/2] + a[(n/2)-1])/2;
else return a[n/2];
}
private static void show(int[] a) {
for(int i=0;i<a.length;i++) System.out.print(a[i] + " ");
System.out.println();
}
private static int[] createSubArr(int[] a, int start){
int[] sub = new int[a.length-start];
for(int i=0;i<a.length-start;i++) sub[i] = a[start+i];
return sub;
}
private static int getMedian(int[] a, int[] b,int n){
int m1,m2;
int start=-1;
int ans = -1;
if(n<=0) return -1;
if(n==1) return (a[0] + b[0])/2;
if(n==2) return (Math.max(a[0],b[0]) + Math.min(a[1],b[1]) )/2;
m1=median(a,n);
m2=median(b,n);
if(m1 < m2) {
if(n%2==0){
start = (n/2)-1;
a = createSubArr(a,start);
}
else {
start = (n/2);
a = createSubArr(a,(n/2));
}
}else{
if(n%2==0){
start = (n/2)-1;
b = createSubArr(b,start);
}
else {
start = (n/2);
b = createSubArr(b,start);
}
}
return getMedian(a,b,n-start);
}
}
感谢。
答案 0 :(得分:0)
您可以向getMedian
添加两个额外参数:a
和b
的起始索引,然后无需复制数据。
此外,而不是代码段:
if (n%2 == 0) {
x = n/2 - 1;
} else {
x = n/2;
}
您只需使用(n-1)/2;
您需要调整以下两种方法来获得O(lg n)
算法(未经测试):
private static int median(int[] a, int a0, int n){
if(n % 2 == 0) return (a[a0 + n/2] + a[a0 + (n/2)-1])/2;
else return a[a0 + n/2];
}
private static int getMedian(int[] a, int a0, int[] b, int b0,int n){
int m1,m2;
int start=-1;
int ans = -1;
if(n<=0) return -1;
if(n==1) return (a[a0] + b[b0])/2;
if(n==2) return (Math.max(a[a0],b[b0]) + Math.min(a[a0+1],b[b0+1]) )/2;
m1=median(a, a0,n);
m2=median(b, b0,n);
if(m1 < m2) {
return getMedian(a, (n-1)/2, b, b0, n - (n-1)/2);
} else {
return getMedian(a, a0, b, (n-1)/2, n - (n-1)/2);
}
}
Offtopic:你自己想出了一个偶数长度阵列的中位数的定义,还是给出了?我认为选择两个“中间元素”中的一个更为常见,无论你最喜欢哪一个。我希望中位数是你输入数组中的一个元素,你的方法无法保证。