求线性表的中位数

1.一个长度为 n(n≥1)的升序序列 S,处在第 n/2 个位置的数称为 S 的中位数。例如,若序列 S1=(11,13,15,17,19),则 S1 的中位数是 15。两个序列的中位数是含它们所有元素的升序序列的中位数。例如,若 S2=(2,4,6,8,20),则 S1 S2 的中位数是 11。现有两个等长升序序列 A B,试设计一个在时间和空间两方面都尽可能高效的算法,找出两个序列 A B 的中位数。假设升序序列采用顺序表存储。顺序表结构描述如下:

# define MaxSize 50 typedef struct

{ ElemType data[MaxSize];

int length;

}SqList;

要求:

  1. 给出算法的基本设计思想;
  2. 根据设计思想,采用 C/C++语言描述算法,关键之处给出简要注释;
  3. 说明你所设计算法的时间复杂度和空间复杂度.

1.第一种思路为暴力求解(没啥好说的)

2.第二种思路为用指针方法(代码如下)

int find( int* a, int* b, int len ) 
{
	int i = 0,j = 0,k = 0;
	for ( ; k < len-1; k++) 
    {
		if ( a[i] < b[j] )
			i++;
		else
			j++;
	}
	return (a[i] < b[j])? a[i]: b[j];
}

3.第三种思路为减治

核心:将升序序列左右两边同时减去相等的数字,中位数不变。

设A的中位数为a,B的中位数为b.

(1)若a = b,则A与B组成的序列的中位数为a。

(2)若a < b,则舍弃A中较小的部分,舍弃B中较大的部分,且两次舍弃的长度一样。

(3)若a > b,则舍弃A中较大的部分,舍弃B中较小的部分,且两次舍弃的长度一样。

重复(1),(2),(3),直到两个序列只剩下一个元素时为止,较小者即为中位数。

分析:

若a = b,很明显是对的,因为在中间位置不影响。

若a > b(不举 a < b,两个一样的)

当序列为奇数时(分析图如下)

当序列为偶数时(分析图如下)

 

则我的代码如下:

int find(SqList* A, SqList* B)
{
    int a = 0,b = 0,end1 = A.length - 1,end2 = B.length - 1,mid1,mid2; //定义A,B序列的首项,末项,中位项
    while(a!= end1 || b!= end2)  //当A,B项只有一个元素时退出循环
    {
        mid1 = (a + end1) / 2;
        mid2 = (b + end2) / 2;
        if(A.data[mid1] == B.data[mid2])  //如果相等,则中位数求出
            return A.data[mid1];
        else if(A.data[mid1] < B.data[mid2])
        {
            if(end % 2 == 0) //当序列长度为奇数时
            {
                a = mid1;  //舍弃A中中位数前面的数并保留A的中位数
                end2 = mid2;  //舍弃B中中位数后面的数并保留B的中位数
            }
            else
            {
                a = mid1 + 1; //舍弃A中中位数后面的数(包括中位数)
                end2 = mid2;  //舍弃B中中位数后面的数并保留B的中位数
            }
        }
        else  //当A.data[mid1] < B.data[mid2]时
        {
             if(end % 2 == 0) //跟前面原理一样,只不过A,B调换了一下位置
            {
                b = mid2;
                end1 = mid1;
            }
            else
            {
                b = mid2 + 1;
                end1 = mid1;
            }
        }
    }
    return A.data[a] < B.data[b] ? A.data[a] : B.data[b]; //两者中最小的即为中位数
}
//因为每次循环求中位数时除以2,所以时间复杂度为O(㏒2n),而空间没有其他的开销,所以空间复杂度为O(1)

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值