演算法——有序陣列中值
阿新 • • 發佈:2018-12-17
題目描述
有兩個已排序陣列A、B,各自大小分別為m,n。找到兩個已排序陣列的中值。
解題思路
將整個集合分為兩個等長的子集,使一邊的值總是大於另一邊。這道題,可以將A、B看作一個整體,然後劃分為左右兩部分L和R,並且滿足 。
當總個數(m+n)位奇數時,結果為:
當總個數(m+n)為偶數時,結果為:
這樣一來,問題簡化為了尋找平分整個集合的方法,假設 ,使用 將陣列A分為A0~Ai-1和Ai~Am-1,因此想要將集合均分,則需要 ,將陣列B分為B0~Bj-1 和Bj~Bn-1,於是陣列分為了如下兩部分。
L | R |
---|---|
A[0],A[1],…,A[i-1] | A[i],A[i+1],…,A[m-1] |
B[0],B[1],…,B[j-1] | B[j],B[j+1],…,B[n-1] |
於是題目轉化為,尋找合適的 ,使得 ,於是我們可以使用二分法來查詢 值,找到 值後,就可以求出結果了。
程式碼
public static double findMedianSortedArrays (int[] a, int[] b) {
//交換陣列,保證m<n
if (a.length > b.length) {
int[] temp = a;
a = b;b = temp;
}
int m = a.length, n = b.length;
int iMin = 0, iMax = m, halfLength = (m+n+1)/2;
while (iMin <= iMax) {
int i = (iMin + iMax)/2;
int j = halfLength - i;
if (i < iMax && b[j-1] > a[i]) {//當前i值較小,增加iMin到i+1處
iMin = i+1;
}else if (i > iMin && a[i-1] > b[j]) {//當前i值較大,減小iMax到i-1處
iMax = i-1;
}else {
int maxLeft = 0;
if (i == 0) {
maxLeft = b[j-1];
} else if (j == 0) {
maxLeft = a[i-1];
} else {
maxLeft = Math.max(a[i-1], b[j-1]);
}
//總個數位奇數時,返回max(L)
if ((m + n)%2==1) {
return maxLeft;
}
int minRight = 0;
if (i == m) {
minRight = b[j];
} else if (j == n) {
minRight = a[i];
} else {
minRight = Math.min(a[i], b[j]);
}
return (maxLeft+minRight)/2.0;
}
}
return 0;
}