天天看点

【数据结构】课后作业——返回中位数

P18.11

分别有m,n个整数存放到一位数组A,B中,将两数组合并并找出合并后数组的中位数。

(1)算法的基本设计思想

新建一个数组,将A,B元素按从小到大的顺序放在新数组中,然后返回。

(2)代码如下

#include <stdio.h>
#include <malloc.h>
#include <math.h>
unsigned int* array(unsigned int i);//C中不能新建数组元素为变量的数组,该函数用于实现这一功能
void main()
{
	int countA, countB;
	scanf("%d", &countA);
	scanf("%d", &countB);
	unsigned int* A = array(countA);
	unsigned int* B = array(countB);
	unsigned int* AB = array(countA+countB);
	int count;
	printf("请输入数组一的元素\n");
	for (count = 0; count < countA; count++)
	{
		scanf("%d", &A[count]);
	}
	printf("请输入数组二的元素\n");
	for (count = 0; count < countB; count++)
	{
		scanf("%d", &B[count]);
	}
	for (count = 0; count < countA; count++)
	{
		printf("%d ", A[count]);
	}
	printf("\n");
	for (count = 0; count < countB; count++)
	{
		printf("%d ", B[count]);
	}
	printf("\n");
	int _countA = 0;
	int _countB = 0;
	for (count = 0; count < countA + countB; count++)
	{
		if (_countA < countA && _countB < countB)
		{
			if (A[_countA] < B[_countB])
			{
				AB[count] = A[_countA];
				_countA++;
			}
			else
			{
				AB[count] = B[_countB];
				_countB++;
			}
		}
		else if (_countA < countA)
		{
			AB[count] = A[_countA];
			_countA++;
		}
		else if (_countB < countB)
		{
			AB[count] = B[_countB];
			_countB++;
		}
		else
			break;
	}
	for (count = 0; count < countA+countB; count++)
	{
		printf("%d ", AB[count]);
	}
	printf("\n");
	int middle;
	middle = AB[(int)floor((double)(countA + countB) / 2)-1];
	printf("中位数为%d", middle);
}
unsigned int* array(unsigned int i)
{
	unsigned int *arr;//指针用于指向数组的首地址
	unsigned int j = 0;
	arr = (unsigned int *)malloc(sizeof(int)*i);//分配数组地址空间
	for (j = i; j>0; j--)
		arr[j - 1] = 0;
	return arr;
}
           

(3)复杂度

时间复杂度O(n)

空间复杂度O(n)

较好的算法

(1)算法的基本设计思想

我们考虑中位数的定义,即该数字前面和后面各有一半的数字。设两有序数组为A,B,长度均为n,中位数为a,b。那么在数组A中有一半比a大,一半比a小。数组b也一样。对于合并后的数组AB,有n个数比中位数ab大,有n个数比ab小。那么,如果我们能不断从A,B中删去元素,使得这个n值不断变小,最后为0,那么剩下的数就是中位数。

考虑合并后数组的中位数出现的范围。因为A,B都是有序的数组,那么对于a,b,有以下几种情况:

A1 a A2

B1 b B2

AB1 ab AB2

  • a>b:这种情况下说明B1中的元素必定在AB1中,A2中的元素必定在AB2中,这两部分都可以舍去。
  • a<b:这种情况下说明A1中的元素必定在AB1中,B2中的元素必定在AB2中,这两部分都可以舍去。
  • a=b:这种情况下说明a和b就是中位数。
  • 注意每次舍弃的都应该是相等的长度。

第一次舍去后可得到两个新的数组,再次使用直到两数组中均只剩一个元素,那么剩下的两个中的较小的就是所求的中位数。

(2)代码如下

#include <stdio.h>
#include <malloc.h>
#include <math.h>
unsigned int* array(unsigned int i);//C中不能新建数组元素为变量的数组,该函数用于实现这一功能
void main()
{
	int countA, countB;
	scanf("%d", &countA);
	scanf("%d", &countB);
	unsigned int* A = array(countA);
	unsigned int* B = array(countB);
	//unsigned int* AB = array(countA+countB);
	int count;
	printf("请输入数组一的元素\n");
	for (count = 0; count < countA; count++)
	{
		scanf("%d", &A[count]);
 	}
	printf("请输入数组二的元素\n");
	for (count = 0; count < countB; count++)
	{
		scanf("%d", &B[count]);
	}
	for (count = 0; count < countA; count++)
	{
		printf("%d ", A[count]);
	}
	printf("\n");
	for (count = 0; count < countB; count++)
	{
		printf("%d ", B[count]);
	}
	printf("\n");
	int _countA1 = 0;
	int _countB1 = 0;
	int _countA2 = countA-1;
	int _countB2 = countB-1;
	int middleA;
	int middleB;
	int middle = 0;
	int mA, mB;
	while (_countA1 != _countA2)
	{
		mA = (int)floor((double)(_countA1 + _countA2) / 2);
		middleA = A[mA];
		mB = (int)floor((double)(_countB1 + _countB2) / 2);
		middleB = B[mB];
		if (middleA == middleB)
		{
			middle = middleA;
			break;
		}
		else if (middleA > middleB)
		{
			if ((_countA1 + _countA2) % 2 == 0)
			{
				_countB1 = mB;
				_countA2 = mA;
			}
			else
			{
				_countB1 = mB + 1;
				_countA2 = mA;
			}
		}
		else
		{
			if ((_countA1 + _countA2) % 2 == 0)
			{
				_countB2 = mB;
				_countA1 = mA;
			}
			else
			{
				_countB2 = mB;
				_countA1 = mA + 1;
			}
		}
	}
	if (middle != 0)
		printf("中位数为%d", middle);
	else
	{
		mA = (int)floor((double)(_countA1 + _countA2) / 2);
		middleA = A[mA];
		mB = (int)floor((double)(_countB1 + _countB2) / 2);
		middleB = B[mB];
		printf("中位数为%d", middleA < middleB ? middleA : middleB);
	}	
}
unsigned int* array(unsigned int i)
{
	unsigned int *arr;//指针用于指向数组的首地址
	unsigned int j = 0;
	arr = (unsigned int *)malloc(sizeof(int)*i);//分配数组地址空间
	for (j = i; j>0; j--)
		arr[j - 1] = 0;
	return arr;
}
           

(3)复杂度

时间复杂度O(logn)

空间复杂度O(1)