Java 两个排序数组的中值:终止条件失败
下面的代码是我按照 您甚至可以在 它不适用于输入数组,例如Java 两个排序数组的中值:终止条件失败,java,arrays,algorithm,sorting,median,Java,Arrays,Algorithm,Sorting,Median,下面的代码是我按照 您甚至可以在 它不适用于输入数组,例如 int[] array1 = {1, 5, 17, 20}; // median is 10 int[] array2 = {4, 8, 13, 19}; int[] array1 = {1, 3, 5, 7, 9, 11}; // median is 6 int[] array2 = {2, 4, 6, 8, 10, 12}; 根据我的分析,问题是,终止条件。一些人认为Geeksforgeks提出的逻辑建议似乎与终止条件有关 (M
int[] array1 = {1, 5, 17, 20}; // median is 10
int[] array2 = {4, 8, 13, 19};
int[] array1 = {1, 3, 5, 7, 9, 11}; // median is 6
int[] array2 = {2, 4, 6, 8, 10, 12};
根据我的分析,问题是,终止条件。一些人认为Geeksforgeks提出的逻辑建议似乎与终止条件有关
(Math.max(array1[low1], array2[low2]) + Math.min(array1[high1], array2[high2]))/2;
但我无法解决它,也无法使它为上述输入工作。
有人能调查一下这个问题,让我知道我犯了什么错误吗?你的主要错误是,当你做纯
intmid1=(low1+high1)/2
您的mid1
总是向左移动,然后您分配mid1
而不考虑此移动,因此每个嵌套比较比较从预定位置向左移动的数组元素,并且由于长度2n
的数组的中位数总是a[n-1]+a[n]/2
,在第一次执行比较后,正在比较错误的数组元素。您似乎错误地实现了方法2的代码块:
if (n % 2 == 0)
return getMedian(ar1 + n/2 - 1, ar2, n - n/2 +1);
else
return getMedian(ar1 + n/2, ar2, n - n/2);
事实上,在findMedian()
入口的简单assert(high2-low2==high1-low1)
会提醒您错误的逻辑,因为对于大小为4的数组,第二个入口产生的数组大小不等。退出条件非常好,因为它直接从方法2的代码复制而来。因此,您需要将分配low1\t
和其他的块更改为以下内容:
assert (high2-low2==high1-low1); // sanity check
int n=high1-low1+1; // "n" from logic
int m1 = median(array1,low1,high1);
int m2 = median(array2,low2,high2);
int low1_t = low1;
int high1_t = high1;
int low2_t = low2;
int high2_t = high2;
if(m1 == m2) {
return m1;
} else if(m1 > m2) {
if (n % 2 == 0) {
high1_t = high1-n/2+1;
low2_t = low2+n/2-1;
} else {
high1_t = high1-n/2;
low2_t = low2+n/2;
}
} else {
if (n % 2 == 0) {
low1_t = low1+n/2-1;
high2_t = high2-n/2+1;
} else {
low1_t = low1+n/2;
high2_t = high2-n/2;
}
}
return findMedian(array1, array2, low1_t, high1_t, low2_t, high2_t);
然后像这样添加函数median
:
static int median(int[] arr, int low,int hig)
{
if ((low+hig)%2 == 0) return arr[(low+hig)/2];
int mid=(low+hig)/2;
return (arr[mid]+ arr[mid-1])/2;
}
完整示例(根据需要更改数组):这是一个有效的代码,应该可以解决您的问题:-
public static void main(String[] args)
{
int[] ar1 = {1, 3, 5, 7, 9, 11};
int[] ar2 = {2, 4, 6, 8, 10, 12};
System.out.println((int) findMedianSortedArrays(ar1,ar2));
}
public static double findMedianSortedArrays(int A[], int B[]) {
int m = A.length;
int n = B.length;
if ((m + n) % 2 != 0) // odd
return (double) findKth(A, B, (m + n) / 2, 0, m - 1, 0, n - 1);
else { // even
return (findKth(A, B, (m + n) / 2, 0, m - 1, 0, n - 1)
+ findKth(A, B, (m + n) / 2 - 1, 0, m - 1, 0, n - 1)) * 0.5;
}
}
public static int findKth(int A[], int B[], int k,
int aStart, int aEnd, int bStart, int bEnd) {
int aLen = aEnd - aStart + 1;
int bLen = bEnd - bStart + 1;
// Handle special cases
if (aLen == 0)
return B[bStart + k];
if (bLen == 0)
return A[aStart + k];
if (k == 0)
return A[aStart] < B[bStart] ? A[aStart] : B[bStart];
int aMid = aLen * k / (aLen + bLen); // a's middle count
int bMid = k - aMid - 1; // b's middle count
// make aMid and bMid to be array index
aMid = aMid + aStart;
bMid = bMid + bStart;
if (A[aMid] > B[bMid]) {
k = k - (bMid - bStart + 1);
aEnd = aMid;
bStart = bMid + 1;
} else {
k = k - (aMid - aStart + 1);
bEnd = bMid;
aStart = aMid + 1;
}
return findKth(A, B, k, aStart, aEnd, bStart, bEnd);
}
publicstaticvoidmain(字符串[]args)
{
int[]ar1={1,3,5,7,9,11};
int[]ar2={2,4,6,8,10,12};
System.out.println((int)findmediansortedarray(ar1,ar2));
}
公共静态双FindMediaTransortedArray(int A[],int B[]){
int m=A.长度;
int n=B.长度;
如果((m+n)%2!=0)//奇数
返回(双)findKth(A,B,(m+n)/2,0,m-1,0,n-1);
否则{//偶数
返回(findKth(A,B,(m+n)/2,0,m-1,0,n-1)
+findKth(A,B,(m+n)/2-1,0,m-1,0,n-1))*0.5;
}
}
公共静态int findKth(int A[],int B[],int k,
int aStart、int aEnd、int bStart、int bEnd){
int aLen=aEnd-aStart+1;
int bLen=弯曲-开始+1;
//处理特殊情况
如果(aLen==0)
返回B[B开始+k];
如果(bLen==0)
返回一个[aStart+k];
如果(k==0)
返回A[aStart]B[bMid]){
k=k-(体重指数-b开始+1);
aEnd=中间;
b开始=体重指数+1;
}否则{
k=k-(中间-aStart+1);
bEnd=bMid;
aStart=aMid+1;
}
返回findKth(A、B、k、aStart、aEnd、bStart、bEnd);
}
我说您不想合并和排序阵列(出于优化原因)对吗?否则会让你的生活easier@cahen是 啊正如您所说,合并和排序将很容易。我也写过这段代码。但这是一种不同的解决问题的方法,以获得更好的时间复杂性。你知道这不起作用的原因吗?你可以在声明时将low1
分配给low1\t
等,以避免所有这些分配;)@霍尔特事实上,这些零没有被使用。我只是需要代码来工作,清理应该只在之后进行。+1。。当我阅读Geeksforgeks代码时,甚至我也认为我在处理奇偶长度案例时没有正确实现。如果我遇到任何问题,我会检查并告诉你。谢谢你的代码。但我在寻找代码中的问题,而不是新代码。如果我的代码没有修复,那么我将研究您的解决方案。
public static void main(String[] args)
{
int[] ar1 = {1, 3, 5, 7, 9, 11};
int[] ar2 = {2, 4, 6, 8, 10, 12};
System.out.println((int) findMedianSortedArrays(ar1,ar2));
}
public static double findMedianSortedArrays(int A[], int B[]) {
int m = A.length;
int n = B.length;
if ((m + n) % 2 != 0) // odd
return (double) findKth(A, B, (m + n) / 2, 0, m - 1, 0, n - 1);
else { // even
return (findKth(A, B, (m + n) / 2, 0, m - 1, 0, n - 1)
+ findKth(A, B, (m + n) / 2 - 1, 0, m - 1, 0, n - 1)) * 0.5;
}
}
public static int findKth(int A[], int B[], int k,
int aStart, int aEnd, int bStart, int bEnd) {
int aLen = aEnd - aStart + 1;
int bLen = bEnd - bStart + 1;
// Handle special cases
if (aLen == 0)
return B[bStart + k];
if (bLen == 0)
return A[aStart + k];
if (k == 0)
return A[aStart] < B[bStart] ? A[aStart] : B[bStart];
int aMid = aLen * k / (aLen + bLen); // a's middle count
int bMid = k - aMid - 1; // b's middle count
// make aMid and bMid to be array index
aMid = aMid + aStart;
bMid = bMid + bStart;
if (A[aMid] > B[bMid]) {
k = k - (bMid - bStart + 1);
aEnd = aMid;
bStart = bMid + 1;
} else {
k = k - (aMid - aStart + 1);
bEnd = bMid;
aStart = aMid + 1;
}
return findKth(A, B, k, aStart, aEnd, bStart, bEnd);
}