1. 程式人生 > >中國大學MOOC—陸軍工程大學資料結構MOOC習題集(2018秋)7-3 中位數

中國大學MOOC—陸軍工程大學資料結構MOOC習題集(2018秋)7-3 中位數

7-3 兩個有序序列的中位數 (25 分)已知有兩個等長的非降序序列S1, S2, 設計函式求S1與S2並集的中位數。有序序列A​0​​,A​1​​,⋯,A​N−1​​的中位數指A​(N−1)/2​​的值,即第⌊(N+1)/2⌋個數(A​0​​為第1個數)。
輸入格式:
輸入分三行。第一行給出序列的公共長度N(0<N≤100000),隨後每行輸入一個序列的資訊,即N個非降序排列的整數。數字用空格間隔。
輸出格式:
在一行中輸出兩個輸入序列的並集序列的中位數。
輸入樣例1:
5
1 3 5 7 9
2 3 4 5 6

輸出樣例1:
4

輸入樣例2:
6
-100 -10 1 1 1 1
-50 0 2 3 4 5
輸出樣例2:
1
解題思路:
(1)將兩個序列合併成一個序列,然後進行排序,排序之後取出新序列的中位數。
(2)中位數演算法:首先將兩個序列分別排序變成兩個升序序列,分別求兩個升序序列A、B的中位數,設為a和b。
若a=b,則a或b即為所求的中位數;
否則,捨棄a、b中較小者所在序列之較小一半,同時捨棄較大者所在序列之較大一半,要求兩次捨棄的元素個數相同。當A長度位奇數時,左半邊=右半邊,直接捨棄即可。當A長度位為偶數時,左半邊+1=右半邊。若a<b,捨棄a的左半邊(包括中點)捨棄b的右半邊(保留中點)始終保持A B 等長。
在保留的兩個升序序列中,重複上述過程,直到兩個序列中均只含一個元素時為止,則較小者即為所求的中位數。
中位數演算法的程式如下:

#include <iostream>
using namespace std;
int al,ar,amid,bl,br,bmid;
int a[100]={0};
int b[100]={0};
int FindMid(int al,int ar,int bl,int br)
{
	while(1)
	{
		amid=(ar+al)/2;
		bmid=(br+al)/2;
		if(al==ar&&bl==br)
		{
			if(a[al]<b[bl])
			return a[al];
			else
			return b[bl];
		}
		else
		{	
			if((ar+al)%2==0)
			{
				if(a[amid]<b[bmid])
				{
					al=amid;
					br=bmid;
				}
				else
				{
					bl=bmid;
					ar=amid;
					
				}
			else
			{
				if(a[amid]<b[bmid])
				{
					al=amid+1;
					br=bmid;
				}
				else
				{
					bl=bmid+1;
					ar=amid;
					}
			}
		}
	}

int main()
{
	int num;
	int result;
	cin>>num;
	for(int i=0;i<num;i++)
	{
		cin>>a[i];
		}
	for(int i=0;i<num;i++)
	{
		cin>>b[i];
		}
	result=FindMid(0,num-1,0,num-1);
	cout<<result<<endl;
	}