1. 程式人生 > >求兩個等長升序序列的中位數

求兩個等長升序序列的中位數

1.        演算法要求

一個長度為L(L≥1)的升序序列S,處在第L / 2(若為小數則去掉小數後加1)個位置的數稱為S 的中位數。例如,若序列S1=(11,13,15,17,19),則S1 的中位數是15,兩個序列的中位數是含它們所有元素的升序序列的中位數。例如,若S2=(2,4,6,8,20),則S1 和S2 的中位數是11。現在有兩個等長升序序列A 和B,試設計一個在時間和空間兩方面都儘可能高效的演算法,找出兩個序列A 和B 的中位數。

2.        演算法思想

分別求出序列A 和B 的中位數,設為a 和b,求序列A 和B 的中位數過程如下:

1)若a=b,則a 或b 即為所求中位數,演算法結束。

2)若a<b,則捨棄序列A 中較小的一半,同時捨棄序列B 中較大的一半,要求捨棄的長度相等;

3)若a>b,則捨棄序列A 中較大的一半,同時捨棄序列B 中較小的一半,要求捨棄的長度相等;

在保留的兩個升序序列中,重複過程1)、2)、3),直到兩個序列中只含一個元素時為止,較小者即為所求的中位數。

3.        演算法實現

int get_middle_number(int a[], int b[], int n)
{
	int			start1 = 0, end1 = n-1, m1;
	int			start2 = 0, end2 = n-1, m2;

	while (start1 != end1 || start2 != end2) {
		m1 = (start1 + end1) / 2;
		m2 = (start2 + end2) / 2;
		if (a[m1] == b[m2])
			return a[m1];
		if (a[m1] < b[m2]) {
			if ((start1+end1) % 2 == 0) {
				start1 = m1;
				end2 = m2;
			} else {
				start1 = m1 + 1;
				end2 = m2;
			}
		} else {
			if ((start1+end1) % 2 == 0) {
				end1 = m1;
				start2 = m2;
			} else {
				end1 = m1;
				start2 = m2 + 1;
			}
		}
	}
	return a[start1] < b[start2] ? a[start1] : b[start2];
}

4.        實現原始碼