选择问题之特定分治策略

选择第k小元素

设 L 是 n 个元素的集合,从 L 中选取第 k 小的元素,其中 1<=k<=n.这里
的第 k 小元素是指,当 L 按从小到大排好序之后,排在第 k 个位置的元素。

算法思想

解决该问题用到的是分治思想
下面引用老师的分析


在这里插入图片描述
算法思想

  • k=|S1|+1,m*就是所要找的第k小的数;以m为划分标准后,比m小的有|S1|个,如果恰巧,k=|S1|+1,则m就是所要找到第k小的数
  • k<=|S1|,归约为在S1中找第k1小的子问题,k1在子问题中的相对位置不变,即k1=k;
  • k>|S1|+1,归约为在S2中找k2位置的子问题,k2相对于S2子问题和k相对于S的关系,即k2=k-|S1|-1。(在S中找k,就是在S2中找k2
  • 在这里插入图片描述

核心伪代码

int Select(int A[], int left, int right, int k)
{
	int p = right - left;//计算数组大小
	if (p < 5)//规模小,直接排序
	{
		sort(A + left, A + right);
		return A[left + k - 1];
	}
	int q = p / 5;//分为q组
	int* M = new int[q];
	for (遍历分组)
	{	//排序后得到中位数
	}
	//对中位数数组进行排序得到Mid
	for (遍历数组)
	{
		if (元素小于mid)
			存入A1数组
		else if (元素等于Mid)
			存入A2
		else//其余情况
			存入A3
	}
	if (若小于mid的数超过k个)
		return Select(A1, 0, count1, k);
	if (若小于mid的数加上等于mid的数超过k个)
		return Mid;
	//其余情况
	return Select(A3, 0, count3, k - count1 - count2);
}

算法分析

下面引用老师的分析


  • 假设n是5的倍数,且n/5是奇数,即n/5=2r+1,于是又|A|=|D|=2r,|B|=|C|=3r+2,n=10r+5。

  • 如果A,D的元素都小于m*,那么它们都加入至S1中,且下一步算法又在这个子问题上递归调用,这对应了归约后子问题的规模的上界,也正好是时间复杂度最坏的情况。

  • 子问题规模为|A|+|C|+|D|=7r+2=7*(n−5)/10 + 2=7*(n/10)−1.5<7*n/10
    表明子问题规模不超过原问题规模的7/10
    W(n)<=W(n/5)+W(7n/10)+tn

    其中,W(n/5)为查找m* 的时间,总规模 n 中选出 n/5 个数来找中位数
    tn 是构造中位数集合,以及A & D和m* 进行比较的时间开销,t 是某个常数
    在这里插入图片描述
    W(n)<=tn+0.9tn+(0.9^2)tn+…=tn(1+0.9+0.92+…)=O(n)

所以最后推导出算法时间复杂度为O(n)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值