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)