兩個排序陣列的中位數

2021-06-09 00:54:24 字數 4183 閱讀 2479

求兩個排序陣列中位數,這道題是很有意思的一道題目,演算法導論中9.3-8題,這題必須在o(logn)的時間複雜度求解,否則肯定悲劇。。。

這題有個關鍵的條件,那就是這兩個陣列長度相等

思路如下:

陣列a:1, 3, 5, 7, 9

陣列b:2, 4, 6, 8, 10

首先取二者的中位數,在o(1)時間複雜度內求出,那麼陣列a的midvalue = 5,陣列b的midvalue = 6,則較小的元素midvalue的左邊所有元素,也就是midposition個,和較大元素右邊的所有元素,都要去掉,由於去掉的元素佔所有元素的一半,所以複雜度為o(logn)。只需要移動begin和end的position即可。

第一輪:

陣列a:1, 3,5, 7, 9

陣列b:2, 4, 6, 8, 10

第二輪:

陣列a:1, 3,5, 7, 9

陣列b:2,4, 6, 8, 10

只剩下兩個元素,由於這種情形下midvalue始終是偏左的元素,因此迴圈無法退出,所以滿足lhsbegin == lhsend - 1和 rhsbegin == rhsend - 1時,迴圈退出!

如果兩個

上述情形是當陣列中有兩個及以上元素才成立,必須考慮兩個陣列只存在乙個元素的情形,那麼直接取較小的元素即可!

#include using namespace std;

int findmidvalue(int *lhs, int *rhs, int size)

else if (lhs[lhsmid] < rhs[rhsmid])

else

}if (lhsbegin == lhsend && rhsbegin == rhsend)

result = min(lhs[lhsbegin], rhs[rhsbegin]);

else if (lhsbegin == lhsend - 1 && rhsbegin == rhsend - 1)

else

}return result;

}void main()

; int rhs = ;

const int size = sizeof lhs / sizeof *lhs;

int result = findmidvalue(lhs, rhs, size);

cout << "mid value = " << result << endl;

}

當兩個陣列長度不等時,這種情形比較複雜:

情形一:

當乙個陣列長度為1,另乙個陣列長度為奇數的情形:

例如a:1  b:2, 3, 4

這個時候的比較策略是,a的元素同b的中位數進行比較,若a的元素較小,則中位數一定是max(a[0], b[mid - 1]),若a的元素較大,則中位數一定是b[mid]

情形二:

例如a: 1  b:2, 3, 4, 5

這個時候的比較策略是,a的元素同b的中位數進行比較,若a的元素較小,則中位數一定是b[mid],若a的元素較大,則中位數一定是min(a[0], b[mid + 1])

下面引申一種情形:

當乙個陣列長度為2,另乙個陣列長度為奇數時:

例如a:1, 3  b:2, 4, 6

如果a[mid] < b[mid],那麼a[mid]肯定不會是中位數,由於a只有兩個元素,那麼a[1]將會是中位數的候選物件,那麼此情形退化為上面第一種情形

下面對乙個例子進行分析:

陣列a:1, 3, 5, 7, 9, 11

陣列b:2, 4, 6, 8

第一輪:

陣列a:1, 3, 5, 7, 9, 11

陣列b:2,4, 6, 8

第二輪:

陣列a:1,3, 5, 7

, 9,11

陣列b:2,4, 6, 8

進行到這裡,那麼刪除將不能再進行下去,可以肯定的是其中乙個陣列只有可能是1個或者2個元素,適用於上面分析的情形。

說下上面的刪除策略:

if (a[amid] < b[bmid])

即刪除較小的左邊元素和較大的右邊元素較小的個數。

刪除策略進行不下去還有一種情況,那就是rightb為0,當rightb為0時,b的元素只有可能是乙個,因為b有多個元素時,b的中位數右邊肯定還存在元素。

不難寫出**如下:

#include using namespace std;

int findmidvalue(int *lhs, int sizelhs, int *rhs, int sizerhs)

else

}else if (lhsleft == 0)

else

}//lhs two elems

else

else

}else}}

else

else

}break;

}lhsbegin = lhsbegin + minvalue;

rhsend = rhsend - minvalue;

} else

else

}else if (rhsleft == 0)

else

}//rhs two elems

else

else

}else}}

else

else

}break;

}lhsend = lhsend - minvalue;

rhsbegin = rhsbegin + minvalue;

} }return result;

}void main()

; int rhs = ;

const int size1 = sizeof lhs / sizeof *lhs;

const int size2 = sizeof rhs / sizeof *rhs;

int result = findmidvalue(lhs, size1, rhs, size2);

cout << "mid value = " << result << endl;

}

(rhsend - rhsbegin) & 0x01成立表示有偶數個陣列,不信用筆畫一畫下標index~~~

關於中位數的其他求法,羅列如下:

1,題目 

有兩個陣列,均已經按公升序排列好,程式設計序計算這兩個陣列的中位數 

要求:要求時間複雜度o(lgn)   空間複雜度o(1) 

例子: 

陣列a:   b     兩陣列合併後   中位數就是中間的那個數: 5 

2,方法: 

對兩個陣列分別二分找解 

對每個元素可以o(1)判斷它在另外乙個陣列應該所在的位置,從而可以判斷選大了還是小了,繼續二分直到找到解為止 

先二分第乙個陣列找解,可選區域為[0,4]。選中a[2]=6,6前面有兩個元素,如果將其插入第二個陣列,那麼6如果是解,則必須前面有4-2=2個元素(排第三位) 

通過比較前後元素發現6放在b中的第三位明顯大了,需要更小的元素,這樣就將下一次二分的區域減了一半. 

在a和b中重複這個過程,直到找到解為止 

3,3,擴充套件 

m個長度為n的排序好的陣列 求中位數 

目前有兩個比較好的演算法 

演算法一 

(1)取所有陣列的最小值和最大值,求出全體的最大值和最小值min max 然後取m=(min+max)/2 

(2)用m在所有陣列中搜尋 找到比m小的數的個數n1 若n1大於m*n/2 則mid=(min+mid)/2 否則mid=(mid+max)/2 

(3)重複上述搜尋一共迴圈log(max-min)次 

演算法二 

(1)取所有陣列的中值排序 

棄掉這個最大值所在陣列的後半部分和最小值所在陣列的前半部分 再將這兩個只剩一半的陣列合併 o(n) 

(2)從合併後的陣列中找出中值插入到之前的中值排序陣列裡 o(logn) 

(3)重複(1)(2),每次迴圈可以捨掉乙個陣列,一共需要迴圈m次

思想與本文實質相同!

兩個排序陣列的中位數

求兩個排序陣列中位數,這道題是很有意思的一道題目,演算法導論中9.3 8題,這題必須在o logn 的時間複雜度求解,否則肯定悲劇。這題有個關鍵的條件,那就是這兩個陣列長度相等 思路如下 陣列a 1,3,5,7,9 陣列b 2,4,6,8,10 首先取二者的中位數,在o 1 時間複雜度內求出,那麼陣...

兩個排序陣列的中位數

兩個排序的陣列a和b分別含有m和n個數,找到兩個排序陣列的中位數,要求時間複雜度應為o log m n 給出陣列a 1,2,3,4,5,6 b 2,3,4,5 中位數3.5 給出陣列a 1,2,3 b 4,5 中位數 3 public double findmediansortedarrays in...

兩個排序陣列的中位數

來自leetcode的兩個排序陣列的中位數 給定兩個大小為 m 和 n 的有序陣列 nums1 和 nums2 請找出這兩個有序陣列的中位數。要求演算法的時間複雜度為 o log m n 你可以假設 nums1 和 nums2 不同時為空。思路 合併陣列 對陣列排序 得到中位數 片.findmedi...