合并有序列表的下界)合并两个有序列表是我们经常会遇到的问题。作为MERGE-SORT的一个子过程,我们在2.3.1节中已经遇到过这一问题。对这一问题,我们将证明在最坏情况下,合并两个都包含nnn个元素的有序列表所需的比较次数的下界是2n−12n−12n−1。
  首先,利用决策树来说明比较次数有一个下界2n−o(n)2n−o(n)2n−o(n)。
  a. 给定2n2n2n个数,请算出共有多少种可能的方式将它们划分成两个有序的列表,其中每个列表都包含nnn个数。
  b. 利用决策树和(a)的答案,证明:任何能够正确合并两个有序列表的算法都至少要进行2n−o(n)2n−o(n)2n−o(n)次比较。
  现在我们来给出一个更紧确界2n−12n−12n−1。
  c. 请说明:如果两个元素在有序序列中是连续的,且它们分别来自不同的列表,则它们必须进行比较。
  d. 利用你对上一部分的回答,说明合并两个有序列表时的比较次数下界为2n−12n−12n−1。
  
  
  a.
  题目问的是有多少种方式将2n2n2n个数划分成两个都包含nnn个数的有序的列表。实际上题目可以转化为求取有多少种方式将2n2n2n个数分成两组,每组都有nnn个数。因为,只要分组确定了,每组都只有一种可能的排序。根据排列组合原理,分组方式一共有C2nn=(2n)!/(n!∙(2n−n)!)=(2n)!/(n!∙n!)C_{2n}^n=(2n)!/(n!∙(2n-n)!)=(2n)!/(n!∙n!)C2nn​=(2n)!/(n!∙(2n−n)!)=(2n)!/(n!∙n!)种。
  
  b.
  为了表示合并两个有序列表的决策树是什么样的,我们举个简单的例子。假设要合并的两个有序列表都包含222个元素,分别为<a,b><a, b><a,b>和<c,d><c, d><c,d>,其中a≤ba ≤ ba≤b并且c≤dc ≤ dc≤d。合并这两个序列的决策树如下图所示。
  
  在决策树中,每个叶结点都是合并后可能的序列,每个非叶结点表示一次比较。上图决策树中,一共有6个叶结点,这符合a的结论,因为C42=6C_4^2=6C42​=6。
  根据a的结论,对于合并两个都包含nnn个元素的有序序列的问题,它的决策树包含(2n)!/(n!∙n!)(2n)!/(n!∙n!)(2n)!/(n!∙n!)个叶结点。假设该决策树的高度为hhh,那么它最多包含2h2^h2h个叶结点。于是有
    (2n)!(n!∙n!)≤2h\frac{(2n)!}{(n!∙n!)} ≤ 2^h(n!∙n!)(2n)!​≤2h
  对该不等式两边取对数,得到
    h≥lg(2n)!(n!∙n!)=lg⁡((2n)!)−2lg⁡(n!)h ≥ {\rm lg}\frac{(2n)!}{(n!∙n!)} = {\rm lg}⁡((2n)!) - 2{\rm lg}⁡(n!)h≥lg(n!∙n!)(2n)!​=lg⁡((2n)!)−2lg⁡(n!)
  令f(n)=lg⁡((2n)!)−2lg⁡(n!)f(n) = {\rm lg}⁡((2n)!) - 2{\rm lg}⁡(n!)f(n)=lg⁡((2n)!)−2lg⁡(n!),有
    f(n)=lg⁡((2n)!)−2lg⁡(n!)=∑i=12nlgi−2∙∑i=1nlgi=∑i=22nlgi−2∙∑i=1n−1lgi−2lgnf(n) = {\rm lg}⁡((2n)!) - 2{\rm lg}⁡(n!) = \sum\limits_{i=1}^{2n}{{\rm lg}i} - 2∙\sum\limits_{i=1}^{n}{{\rm lg}i} = \sum\limits_{i=2}^{2n}{{\rm lg}i} - 2∙\sum\limits_{i=1}^{n-1}{{\rm lg}i} - 2{\rm lg}nf(n)=lg⁡((2n)!)−2lg⁡(n!)=i=1∑2n​lgi−2∙i=1∑n​lgi=i=2∑2n​lgi−2∙i=1∑n−1​lgi−2lgn
  直接对对数求和不方便,可以采用积分近似求和的方法(参考《算法导论》附录A.2)。于是有
  
  根据以上分析,可以得到决策树的高度h≥2n–o(n)h ≥ 2n–o(n)h≥2n–o(n)。这也证明了任何能够正确合并两个有序列表的算法都至少要进行2n−o(n)2n−o(n)2n−o(n)次比较。

c.
  简要说明一下。假设有两个待合并的有序序列<A1,A2,…,An><A_1, A_2, …, A_n><A1​,A2​,…,An​>和<B1,B2,…,Bn><B_1, B_2, …, B_n><B1​,B2​,…,Bn​>,我们现在要确定两个元素AiA_iAi​和BjB_jBj​的次序。为简化分析,假设所有元素都不相等。确定二者的次序只有两种方法:
  (1) 二者直接比较:Ai<BjA_i < B_jAi​<Bj​或者Ai>BjA_i > B_jAi​>Bj​。
  (2) 通过其他元素间接比较:Ai<x<BjA_i < x < B_jAi​<x<Bj​或者Ai>x>BjA_i > x > B_jAi​>x>Bj​,以及Ai<x<…<y<BjA_i < x < … < y < B_jAi​<x<…<y<Bj​或者Ai>x>…>y>BjA_i > x > … > y > B_jAi​>x>…>y>Bj​,
  如果通过第(2)种方式,那么说明至少存在一个元素xxx,使得Ai<x<BjA_i < x < B_jAi​<x<Bj​或者Ai>x>BjA_i > x > B_jAi​>x>Bj​成立,所以AiA_iAi​和BjB_jBj​肯定不相邻,因为二者之间至少间隔一个元素xxx。反过来,如果AiA_iAi​和BjB_jBj​相邻,说明肯定不存在这样的元素xxx,使得Ai<x<BjA_i < x < B_jAi​<x<Bj​或者Ai>x>BjA_i > x > B_jAi​>x>Bj​成立。这说明,如果AiA_iAi​和BjB_jBj​相邻,只能通过第(1)种方式来确定二者的次序,即二者直接比较。
  多提一句,在排序问题中,如果在排序后的序列中两个元素相邻,那么二者也必须进行直接比较,原因与上面是一样的。

d.
  注意,本题要证明的是:在最坏情况下,合并两个有序列表时的比较次数的下界为2n−12n−12n−1。
  利用c的结论,如果有两个来自不同序列的元素,并且二者在合并后的序列中相邻,那么二者必须进行直接比较。我们只需要统计在合并后的序列中,有多少对相邻的元素来自不同的序列,就可以知道合并过程中至少需要比较多少次。
  假设有两个待合并的有序序列<A1,A2,…,An><A_1, A_2, …, A_n><A1​,A2​,…,An​>和<B1,B2,…,Bn><B_1, B_2, …, B_n><B1​,B2​,…,Bn​>。最好的情况是合并后的序列中只有111对相邻的元素来自不同的序列,比如<A1,A2,…,An,B1,B2,…,Bn><A_1, A_2, …, A_n, B_1, B_2, …, B_n><A1​,A2​,…,An​,B1​,B2​,…,Bn​>,只有一对相邻元素AnA_nAn​和B1B_1B1​,二者来自不同的序列。因此,最好情况下,至少只需要比较一次。
  而最坏情况发生在合并之后,任意两个相邻的元素都来自不同的序列,比如<A1,B1,A2,B2,…,An,Bn><A_1, B_1, A_2, B_2, …, A_n, B_n><A1​,B1​,A2​,B2​,…,An​,Bn​>。合并后的序列一共有2n2n2n个元素,相邻的元素一共有2n−12n−12n−1对。其中每一对相邻的元素都来自不同的序列,那么合并过程至少需要比较2n−12n−12n−1次。因此在最坏情况下,合并两个有序列表时的比较次数的下界为2n−12n−12n−1。

算法导论 — 思考题8-6 合并有序列表的下界相关推荐

  1. 有序序列中的i个最大数(算法导论思考题9-1)

    有序序列中的i个最大数 (算法导论思考题9-1) a 时间复杂度O(nlgn+i) //总共时间复杂度O(nlgn+i) vector<int> i_largest_number_in_o ...

  2. 算法导论 思考题1-1

    算法导论-思考题1-1 1-1(运行时间的比较)假设求解问题的算法需要 f(n)f(n)f(n)微秒(microseconds),对下表中每个函数f(n)f(n)f(n)和时间ttt可以确定在时间tt ...

  3. leetcode 21.合并有序列表(js)

    合并有序列表 题目 测试点 描述 题解 方法1 方法2 题目 将两个升序链表合并为一个新的 升序 链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的. 测试点 输入:l1 = [1,2,4], ...

  4. 算法导论 思考题 9-3

    (小顺序统计量)要在n个数中选出第i个顺序统计量,SELECT在最坏情况下需要的比较次数T(n)满足T(n) = (n).但是,隐含在记号中的常数项是非常大的.当 i 相对于n来说很小时,我们可以实现 ...

  5. 算法导论 思考题2-4

    思考题2-4(逆序对) 假设A[1..n]A[1..n]A[1..n]是一个有nnn个不同数的数组,若i<ji<ji<j且A[i]>A[j]A[i]>A[j]A[i]&g ...

  6. 算法导论 思考题6-3(Young氏矩阵)

    思考题6-3(Young氏矩阵)在一个m×nm\times nm×n的Young氏矩阵(Young tableau)中,每一行的数据都是从左到右排序的,每一列的数据都是从上到下排列的.Young氏矩阵 ...

  7. 算法导论 — 思考题15-10 投资策略规划

    (投资策略规划)你所掌握的算法知识帮助你从Acme计算机公司获得了一份令人兴奋的工作,签约奖金1万美元.你决定利用这笔钱进行投资,目标是10年后获得最大回报.你决定请Amalgamated投资公司管理 ...

  8. 算法导论 思考题12-1

    12-1(带有相同关键字的二叉搜索树)相同关键字给二叉搜索树的实现带来了问题. a.  当用TREE-INSERT将nnn个其中带有相同关键字的数据插入到一棵初始为空的二叉搜索树中时,其渐进性能是多少 ...

  9. 算法导论 思考题9-2

    9-2 (带权中位数)对分别具体以正权重w1,w2,⋯,wnw_1,w_2,\dotsb,w_nw1​,w2​,⋯,wn​,且满足∑i=1nwi=1\sum_{i=1}^{n}{w_i=1}∑i=1n ...

最新文章

  1. 让梦露和龙妈学着你说话,只需一张静态图和一个视频 | 项目开源
  2. SQL XML 字段操作
  3. (转载)关于安装Ubuntu系统时提示“分配到/的分区/dev/sdax开始于xxxx字节,使用磁盘的最小对齐,这可能造成非常差的性能...的解决办法
  4. Python和Java就业前景对比
  5. jakob slam_Jakob Nielsen针对用户界面设计的第二种可用性启发法
  6. @Async join
  7. Qt下Undefined reference to 'vtable for xxx'
  8. php中的CURL库
  9. 小孔成像总结_【伟林教育】初中生必看:中考物理解题技巧+方法总结,可以说很到位了!...
  10. atitit.验证码识别step4--------图形二值化 灰度化
  11. anylogic和java_使用Anylogic访问服务器及文件系统
  12. love2d ffi 窗口移动
  13. 麒麟桌面系统添加字体
  14. 波士顿房价预测实验报告
  15. html 通过name选择器,用name方式获得选择器总结
  16. Android锁屏Demo
  17. Fragstats计算景观格局指数不出结果和分维数PAFRAC出现N/A的问题
  18. 机房收费系统问题集(2)——移动登陆界面+show出子窗体
  19. opencv的逻辑运算bitwise详解
  20. HDFS读写流程以及多节点、单节点磁盘负载均衡

热门文章

  1. 离散数学实验(三)集合的基本运算
  2. Flyback的Cross Regulation
  3. 南加大计算机专业本科sat要求,南加州大学申请条件有哪些?
  4. Android最好用的项目框架搭建
  5. 知乎里面别人发的视频怎么保存下来?
  6. C++面向对象程序设计概念全总结(六)--最全的概念总结
  7. C语言字符串、转义字符
  8. java设计火车的类,JAVA课程设计--火车票管理系统
  9. 这样做框架结构图,让你的PPT更有创意!
  10. 小米2016AP2594计算机参数,小米6完整详细参数配置表:骁龙835处理器CPU+6GB内存