问题描述

把数列\((x_1,x_2,\cdots,x_n)\)变换顺序为\((x_{p(1)},x_{p(2)},\cdots,x_{p(n)})\),其中\(p\)是\(A=\{1,2,3,\cdots,n\}\)的一个排列,要求只使用\(O(1)\)的额外空间。例如,当数列为\((10,20,30,40)\),\(p\)为\((3,1,2,4)\)时得到的数列是\((30,10,20,40)\).

算法描述

对于映射\(p:A\rightarrow A\),它的含义是“排列后的数组每个元素从哪里来”。即:变换后,数组下标\(k\)处的数从变换前的下标\(p(k)\)处来。变换后下标为\(p(k)\)处的数从变换前下标为\(p(p(k))\)处的数来……因此我们可以把这条变换的链记为:

\[k\leftarrow p(k)\leftarrow p(p(k))\leftarrow \cdots \]

每一个下标都在唯一的一个“圈”内(原文这里的用词为"cycle")。举个例子:

对于给定的一个排列:

\[p=(8,2,7,1,6,9,3,4,5) \]

我们可以观察到这样的规律:

\[\left\{\begin{array}{l}p(1)=8,p(8)=4,p(4)=1\\p(2)=2\\p(3)=7,p(7)=3\\p(5)=6,p(6)=9,p(9)=5\end{array}\right. \]

对于括号中的每一行。最后一个等式右侧的数在\(p\)映射下的像,等于第一个等式左侧\(p\)作用的原像。对于每一个这样的圈,我们都能用大小为\(O(1)\)的额外空间完成数字的交换。而这个交换我们从每个圈中的最小数开始做。

代码描述:
for (int j = 1;j <= n;j++) {int k = p(j);//nwhile (k > j) {//n+ak = p (k);//a}if(k == j) {int y = x[j],l = p[k];//bwhile (l != j) {//b+cx[k] = x[l];//ck = l;//cl = p(k);//c}x[k] = y;//b}
}
/*这里b是变换p中"圈"的个数,c+b=na的含义是:对于每个j,在j所在的圈中第一个不大于j的数k距离p(j)的距离之和*/
最坏情况

最坏的情况如下

\[p=(2,3,\cdots,n,1)\\a=(n-1)+(n-2)+\cdots +0=\frac{n^2-n}{2}\\b=1 \]

此为\(a\)的最坏情况和\(b\)的最好情况。

\[p=(1,2,\cdots,n-1,n)\\a=0\\b=n \]

此为\(a\)的最好情况和\(b\)的最坏情况。

b的平均值分析

对于上面引用的\(p\)的实例:

\[p=(8,2,7,1,6,9,3,4,5) \]

把所有的圈按照下述规则排列

1.圈内最小的数排在第一

2.圈内最小的数较大的,排在前面

则以上的\(p\)将变为\((5,6,9)(3,7)(2)(1,8,4)\),设\(q=(5,6,9,3,7,2,1,8,4)\).则这样的\(p\)到\(q\)的变换构成了一个排列到排列的双射。

这样,我们就可以把求\(b\)的值转化为求\(\{1,2,\cdots,n\}\)中满足\(q(j)=\min\{q(i)|i\le i \le j \}\)的\(j\)的个数。使得满足这样条件的\(j\)的个数为\(k\)的\(n\)元排列数共有\(\left[\begin{array}{c}n\\k\end{array}\right]\)种。(第一类Stirling数)

所以:

\[\overline{b}=\frac{\sum_{i=1}^n\left[\begin{array}{c}n\\i\end{array}\right]\times i}{n!}=H_n=\ln n+O(1) \]

(当\(n\)充分大时,\(O(1)\)的值收敛到欧拉常数)

\[\sigma^2=H_n-H_n^{(2)} \]

其中

\[H_n=1+\frac{1}{2}+\frac{1}{3}+\cdots+\frac{1}{n}\\H_n^{(2)}=1^2+(\frac{1}{2})^2+(\frac{1}{3})^2+\cdots+(\frac{1}{n})^2 \]
a的平均值分析
\[p=(8,2,7,1,6,9,3,4,5)\\q=(5,6,9,3,7,2,1,8,4)\\ \]

我们定义如下函数

\[y(i,j)=\left\{\begin{array}{l}1,\quad q(i)<q(k),\exist k \in (i,j]\\0,\quad else\end{array}\right. \]

\[a=\sum_{1\le i<j\le n}y(i,j) \]

\[\overline{y(i,j)}=\frac1{j-i+1}\\\overline a =\sum_{1\leq i<j\leq n}\overline{y(i,j)}=\sum_{1\leq i<j\leq n}\frac1{j-i+1}=\sum_{2\leq r\leq n}\frac{n+1-r}r \]

其中,\(r=j-i+1\)

由上式:

\[\begin{aligned}\overline a&=\sum_{2\leq r\leq n}\frac 1r- \sum_{2\leq r\leq n}1\\&=(n+1)(H_n-1)-(n-1)\\&=(n+1)H_n-2n\\&=n\ln n +O(n)\\&=O(n\log n)+O(n)\end{aligned} \]
\[\sigma^2=2n^2-(n+1)^2H_n^{(2)}-(n+1)H_n+4n \]

由上面计算的\(b\)的均值\(\overline b=\ln n +O(1)=O(\log n)\)

所以算法的平均时间复杂度是\(O(n\log n)\)

《Mathematical Analysis of Algorithms》中有关“就地排列”(In Situ Permutation)的算法分析相关推荐

  1. 【翻译】Mathematical Analysis of Algorithms

    这是Knuth 的一篇论文,原文下载在这里有:http://download.csdn.net/detail/u013012544/6982095,是北京大学本科生算法设计与分析2014年春季课程的必 ...

  2. knuth《mathematical analysis of algorithms》学习笔记

    参考资料:就这篇论文,以及小班课同学的ppt,以及助教给出的一些指点 个人觉得最有成就感的是在appendix 1 把tally优化的那一步计算过程搞清楚了 不多说,上图 特别感谢小班课同学的讲解,很 ...

  3. Lecture 1 Analysis of Algorithms

    2019独角兽企业重金招聘Python工程师标准>>> Analysis of Algorithms The theoretical study of computer progra ...

  4. python中如何求列表中的和_python实现求解列表中元素的排列和组合

    求解列表中元素的排列和组合问题这个问题之前就遇到过几次没有太留意,最近在做题的时候遇上挺多的排列组合问题的,想来有必要温习一下了,今天花点时间写一下,之前都是手工写的,后来知道可以直接使用python ...

  5. 计算机工作表中按升序排列,计算机文化基础上机指导

    本书是与<计算机文化基础>配套使用的上机指导书,主要内容包括操作系统Windows XP应用实验.文字处理wofd 2003应用实验.电子表格Excel 2003应用实验.演示文稿Powe ...

  6. Principles Of Mathematical Analysis, Third Edition免费下载地址

    walter rudin的大作 Principles Of Mathematical Analysis 下载地址: https://vdoc.pub/download/principles-of-ma ...

  7. 编写一个能将给定非负整数列表中的数字排列成最大数字的函数

    编写一个能将给定非负整数列表中的数字排列成最大数字的函数.例如,给定[50,2,1,9],最大数字为95021. public class TestFindMaxNum { /** * @param ...

  8. python中按照文件夹中文件的排列顺序读取文件内容,python文件显示和windows目录显示一致

    原创 python中按照文件夹中文件的排列顺序读取文件内容 2018-12-06 11:49:18 途径北海道 阅读数 3891 更多 分类专栏: python 版权声明:本文为博主原创文章,遵循 C ...

  9. 将给定非负整数列表中的数字排列成最大数字的2种方法。例如,给定[50,2,1,9],最大数字为95021。

    一.题目简介 编写一个能将给定非负整数列表中的数字排列成最大数字的函数.例如,给定[50,2,1,9],最大数字为95021. 此处以如下数组为例:Integer[] num=new Integer[ ...

最新文章

  1. .condarc文件是什么
  2. CTFshow 命令执行 web55
  3. PAT甲级题目翻译+答案 AcWing(字符串处理)
  4. 小程序获取微信用户绑定的手机号
  5. 奇奇怪怪的知识增加了,大括号的历史你知道吗?
  6. wxpython多线程_WxPython 4.0.4多线程访问UI
  7. 机器学习经典算法笔记——PCA和梯度上升算法
  8. qq语音按住ctrl就静音怎么解决_绝地求生大逃杀:语音故障的解决办法
  9. ABAP 读取FTP文件
  10. Mydumper 多线程备份工具
  11. 曲面上的测地线 MATLAB,§6曲面上的测地线.PDF
  12. BOOTCAMP U盘安装WIN7一直显示无法创建可引导的USB驱动器
  13. python 爬虫--利用百度图片处理OCR识图API进行验证码识别,并通过python、requests进行网站信息爬取(二)实战
  14. 摩尔条纹拯救我的3D检测
  15. oracle if else怎么用,oracle if else语句使用介绍
  16. anaconda3里pkgs可以删除吗,我试过conda clean -a,但用完之后还有10个G,吐血,C盘没空间了,pkgs删除影响虚拟环境吗,毕竟base大多数人用不到啊,求教
  17. 书评:《软件创新之路-冲破高技术营造的牢笼》
  18. 转型AI ,80后华为Java工程师的故事
  19. 表单验证字母数字中文常用正则
  20. Python06——String04字符串切片

热门文章

  1. 为什么 Android 必须在主线程更新 UI ?
  2. Github Star 过万!用这款免费工具代替收费的Navicat,我看行
  3. for in | for of | foreach 的小坑
  4. smart checkout、force checkout、don`t checkout
  5. jansson库使用
  6. PAT考试乙级1002之写出这个数
  7. Anaconda+opencv-python安装教程
  8. python抓取招聘数据_Python3获取拉勾网招聘信息的方法实例
  9. javascript描述符descriptor详解
  10. anaconda2/bin/../lib/libgomp.so.1: version `GOMP_4.0' not found 问题的解决办法