数据结构——顺序表习题解(II)

数据结构顺序表统考真题算法解析

本题目来自王道考研教材,结合答案给出个人的一些写法。
1.【统考真题】一个长度为L的升序序列S,处在第L/2上取整的数字称之为它的中位数,例如,若序列S1=(11,13,15,17,19),则S1的中位数为15,两个序列的中位数是他们所有的元素组成的升序序列的中位数。例如,若S2=(2,4,6,8,20)则S1,S2的中位数是11,现在有两个等长升序序列A,B。试求一个在时间和空间两方面尽可能高效的算法,找出A和B的中位数。要求:
1)给出算法的基本思想
2)写出代码,关键之处给出注释
3)说明此算法的时间复杂度和空间复杂度

难度:适中:定理的证明较难想到,O(logn)的算法不好想,需要对中位数的性质和概念有较深刻的理解。
思想:
若用归并排序,则一定时间复杂度较高,本体应该采用减治法的思想:
设序列A的中位数为am,序列B的中位数为bm
定理1:A和B的中位数cm大小一定介于am和bm之间

简要证明:由中位数定义,假设A和B中有n个数字(为了方便这里设n为奇数,偶数证明同理),则必然有(n-1)/2个数小于等于am,有(n-1)/2个数大于等于bm。
则分析一下:
1.若am=bm时,则中位数必然为am(或者说bm),因为此时必然有(n-1)个数字小于等于am,有(n-1)个数字大于等于am,am必然为中位数。
2.若am<bm(am>bm同理):若此时cm<am,则必然有cm<am<bm,则此时必然有不包含bm的(n-1)/2个数大于等于bm,也有不包含am在内的(n-1)/2个数大于等于am,则必然至少有2*(n-1)/2+1+1个数字大于cm,即至少有(n+1)个数字大于cm,则cm必不可能为中位数。

由上述证明我们思考一下怎么做最快:
我们取A的中位数am,B的中位数bm,由上述定理可知,AB的中位数一定介于am和bm之间,若此时
1.am=bm,由中位数定义,am即为中位数
2.am<bm, 则我们可以舍弃am之前的数字和bm之后的数字(两边舍弃的数量必须相等),这样能保证大于中位数和小于中位数的数字个数相等,然后再舍弃数字后的新数组A’ B’中继续进行这一操作,直到出现1中条件或者两数组都只剩一个元素为止,由定义,这时候取较小的那个元素即可。
3.am>bm,同理
此算法每次将数组规模缩减一半,所以时间复杂度O(logn) 空间复杂度O(1)

#include <iostream>
using namespace std;
int findMid(int *a, int *b, int n)
{
   
   
	int s1 = 0, s2 = 0, d1 = n - 1, d2 = n - 1;
	//用s表示首指针,d表示尾指针。
	while (s1 != d1 || s2 != d2) 
	{
   
   
		int mid1 = (s1 + d1) / 2;
		int mid2 = (s2 + d2) / 2;
		if (a[mid1] == b[mid2]) return a[mid1];
		if (a[mid1] < b[mid2]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值