算法导论习题—排序、最坏情况线性时间选择算法、小顺序统计量

40 篇文章 6 订阅
26 篇文章 2 订阅
本文探讨了排序算法的稳定性,指出插入排序、归并排序和计数排序是稳定的,并提出了一种使任何排序算法稳定的方法。接着,针对数字位数不同的整数数组,提出了能在O(n)时间复杂度内完成排序的基数排序改进策略。此外,针对SELECT算法找第iii小元素的问题,提出了优化方案,确保在最坏情况下比较次数为Θ(n),且当iii小于n/2时,只需进行n+O(logn)次比较。
摘要由CSDN通过智能技术生成

1. 1. 1. 下面的排序算法中哪些是稳定的:插入排序、归并排序、堆排序、快速排序和计数排序?给出一个能使任何排序算法都稳定的方法。你所给出的方法带来的额外时间和空间开销是多少?

​ 插入排序、归并排序、计数排序是稳定的。

​ 将数组元素的下标也考虑在比较过程中,即对于原始数组 a r r arr arr的每一个元素 a r r [ i ] arr[i] arr[i]都建立一个结构体 a [ i ] : { v a l u e : a r r [ i ] , i n d e x : i } a[i]:\{value:arr[i],index:i\} a[i]{value:arr[i],index:i}存入结构体数组 a a a中,在比较大小时,当 a [ i ] . v a l u e < a [ j ] . v a l u e a[i].value<a[j].value a[i].value<a[j].value或者 a [ i ] . v a l u e = = a [ j ] . v a l u e & & a [ i ] . i n d e x < a [ j ] . i n d e x a[i].value==a[j].value\&\&a[i].index<a[j].index a[i].value==a[j].value&&a[i].index<a[j].index时我们认为 a [ i ] < a [ j ] a[i]<a[j] a[i]<a[j],否则认为 a [ i ] > a [ j ] a[i]>a[j] a[i]>a[j],按照这个规则进行排序可以保证任意的排序算法均是稳定的,需要的空间是原来的两倍,额外时间在于 a [ i ] . v a l u e = = a [ j ] . v a l u e a[i].value==a[j].value a[i].value==a[j].value时对 i n d e x index index进行比较的时间,但在线性时间内,不影响总体时间复杂度。

2. 2. 2.给定一个整数数组,其中不同的整数所包含的数字的位数可能不同。但该数组中,所有整数中包含的总数字位数为 n n n。设计算法使其可以在 O ( n ) O(n) O(n)时间内对该数组进行排序。

设第 i i i个整数的位数为 c i c_i ci,有 m m m个整数,则 ∑ i = 1 m c i = n \sum\limits^{m}_{i=1}c_i=n i=1mci=n,若最高位数为 c m a x ≤ n c_{max}\le n cmaxn,则此时使用基数排序的时间复杂度为 Θ ( c m a x ⋅ m ) \Theta(c_{max}·m) Θ(cmaxm),不满足 O ( n ) O(n) O(n)时间复杂度的要求。

​ 考虑将数组先按数字位数进行分组,再对每一组采用基数排序,对第 i i i个有 c i c_i ci位的整数,确定它的位数需要的时间为 c i c_i ci,则确定所有分组需要的时间为 ∑ i = 1 m c i = n = Θ ( n ) \sum\limits^{m}_{i=1}c_i=n=\Theta(n) i=1mci=n=Θ(n)。假设总共分为 x x x组,对于第 k k k组,该组的每个元素位数为 c k c_k ck,有 m k m_k mk个元素,总位数及总元素个数分别为 ∑ k = 1 x c k = n , ∑ k = 1 x m k = m \sum\limits^{x}_{k=1}c_k=n,\sum\limits^{x}_{k=1}m_k=m k=1xck=n,k=1xmk=m,对第 k k k组采用基数排序的时间复杂度为 Θ ( c k ⋅ m k ) \Theta(c_k·m_k) Θ(ckmk),总时间复杂度为 ∑ k = 1 x Θ ( c k ⋅ m k ) = Θ ( c 1 m 1 ) + Θ ( c 2 m 2 ) + … + Θ ( c x m x ) = Θ ( n ) \sum\limits^{x}_{k=1}\Theta(c_k·m_k)=\Theta(c_1m_1)+\Theta(c_2m_2)+…+\Theta(c_xm_x)=\Theta(n) k=1xΘ(ckmk)=Θ(c1m1)+Θ(c2m2)++Θ(cxmx)=Θ(n),满足在 O ( n ) O(n) O(n)时间内进行排序的要求。

3 3 3.(小顺序统计量) S E L E C T SELECT SELECT算法(找第 i i i小的元素)最坏情况下的比较次数 T ( n ) = Θ ( n ) T(n) =\Theta(n) T(n)=Θ(n),但是其中的常数项是非常大的。请对其进行优化,使其满足:
1. 在最坏情况下的比较次数为 Θ ( n ) \Theta(n) Θ(n)
2. 当 i i i是小于 n / 2 n/2 n/2的常数时,最坏情况下只需要进行 n + O ( log ⁡ n ) n+ O(\log n) n+O(logn)次比较。

将输入的数组划分为 ⌊ n / 2 ⌋ \lfloor n/2 \rfloor n/2组,比较次数为 ⌊ n 2 ⌋ \lfloor \cfrac{n}{2} \rfloor 2n,划分后每组有 2   o r   1 2\ or\ 1 2 or 1个元素,然后令每组的较小元素构成一个集合,并对该集合递归执行划分操作,当要找的第 i i i个元素 i ≥ n 2 i\ge \cfrac{n}{2} i2n时,跳出递归,此时比较次数为 U i ( ⌈ n 2 ⌉ ) U_i(\lceil \cfrac{n}{2} \rceil) Ui(⌈2n⌉),再对该较小元素集合中的前 i i i个数和对应的较大元素集合中的前 i i i个数执行 S e l e c t Select Select算法,共有 2 i 2i 2i个数字,若初始存在只有一个元素的分组,则将该元素加入这 2 i 2i 2i个数中参与比较,此比较次数为 T ( 2 i ) T(2i) T(2i)

步骤 1 1 1:对于输入的 n n n个数,判断是否满足 i ≥ n 2 i\ge\cfrac{n}{2} i2n,不满足则执行步骤 3 3 3,若满足则对数组两两比较,需比较 ⌊ n 2 ⌋ \lfloor \cfrac{n}{2} \rfloor 2n次,得到两部分,其中一部分由各数对中较大数组成,另一部分由较小数组成

步骤 2 2 2:判断需要找的第 i i i小的数, i i i是否 ≥ \ge 由当前较小数组成的集合元素数量 n n n的一半,即是否满足 i ≥ n 2 i\ge\cfrac{n}{2} i2n,若满足则继续执行步骤 1 1 1,若不满足,则执行步骤 3 3 3

步骤 3 3 3:采用 S e l e c t Select Select方法对最后分组进行划分,此时前 i i i个数是该分组最小的 i i i个数,对应的较大元素的分组的元素依次大于该分组,取两个分组中前 i i i个数,若初始存在只有一个元素的分组,则将该元素加入这 2 i 2i 2i个数中参与比较,再对这 2 i 2i 2i 2 i + 1 2i+1 2i+1个数执行 S e l e c t Select Select算法

得到:
U i ( n ) = { T ( n )                   i ≥ n 2 ⌊ n 2 ⌋ + U i ( ⌈ n 2 ⌉ ) + T ( 2 i )     e l s e U_i(n)= \left\{ \begin{aligned} &T(n)\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ i\ge \frac{n}{2} \\ &\lfloor \cfrac{n}{2} \rfloor+U_i(\lceil \cfrac{n}{2} \rceil)+T(2i) \ \ \ else\\ \end{aligned} \right. Ui(n)= T(n)                 i2n2n+Ui(⌈2n⌉)+T(2i)   else
i < n 2 i<\cfrac{n}{2} i<2n时,比较次数为 ⌊ log ⁡ 2 ( n 2 i ) ⌋ \lfloor \log_2(\cfrac{\frac{n}{2}}{i}) \rfloor log2(i2n)⌋,最后运行一次 S e l e c t Select Select算法,则总次数为 ⌊ n 2 ⌋ + ⌊ n 4 ⌋ + … + T ( 2 i ) < n + ( log ⁡ 2 ( n 2 i + 1 ) T ( 2 i ) = n + O ( T ( 2 i ) log ⁡ 2 ( n i ) ) \lfloor \cfrac{n}{2} \rfloor+\lfloor \cfrac{n}{4} \rfloor+…+T(2i)<n+(\log_2(\cfrac{\frac{n}{2}}{i}+1)T(2i)=n+O(T(2i)\log_2(\cfrac{n}{i})) 2n+4n++T(2i)<n+(log2(i2n+1)T(2i)=n+O(T(2i)log2(in)),当 i i i为小于 n / 2 n/2 n/2的常数时, T ( 2 i ) 、 log ⁡ 2 ( i ) T(2i)、\log_2(i) T(2i)log2(i)也为常数,则总次数为 n + O ( log ⁡ n ) n+O(\log n) n+O(logn)

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

之墨_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值