问题描述

把数列\((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);//n
while (k > j) {//n+a
k = p (k);//a
}
if(k == j) {
int y = x[j],l = p[k];//b
while (l != j) {//b+c
x[k] = x[l];//c
k = l;//c
l = p(k);//c
}
x[k] = y;//b
}
}
/*
这里b是变换p中"圈"的个数,c+b=n
a的含义是:对于每个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》中有关“选择第t大的数”的算法分析

    开头废话 这个问题是Donald.E.Knuth在他发表的论文Mathematical Analysis of Algorithms中提到的,这里对他的算法分析过程给出了更详细的解释. 问题描述: 给 ...

  2. "Mathematical Analysis of Algorithms" 阅读心得

    "Mathematical Analysis of Algorithms" 阅读心得 "Mathematical Analysis of Algorithms" ...

  3. 算法分析 Analysis of Algorithms -------GeekforGeeker 翻译

    算法分析 Analysis of Algorithms 为什么要做性能分析?Why performance analysis? 在计算机领域有很多重要的因素我们要考虑 比如用户友好度,模块化, 安全性 ...

  4. 《Principles of Mathematical Analysis》-chaper1-实数系与复数系

    今天我们开始简单的介绍数学分析这门课程,参考教材是Walter Rudin著的<Principles of Mathematical Analysis> 对于一门新课你最开始可能会问的是: ...

  5. GridView控件中加自动排列序号

    GridView控件中加自动排列序号 为 Gridview 增加一个新的空白列,如下: <asp:BoundField  HeaderText="序号">    < ...

  6. 6.046 Design and Analysis of Algorithms

    课程信息 6.046 Design and Analysis of Algorithms

  7. Lecture notes of Mathematical analysis

    Lecture notes of Mathematical analysis Preliminary theory Teaching purpose: Mathematical analysis is ...

  8. 排列计数(permutation)

    排列计数(permutation) 题目描述 求有多少种长度为n的序列A,满足以下条件: 1) 1~n这n个数在序列中各出现了一次 2) 若第i个数A[i]的值为i,则称i是稳定的.序列恰好有m个数是 ...

  9. Analysis of Algorithms

    算法分析 Introduction 有各种原因要求我们分析算法,像预测算法性能,比较不同算法优劣等,其中很实际的一条原因是为了避免性能错误,要对自己算法的性能有个概念. 科学方法(scientific ...

随机推荐

  1. ORB-SLAM2 运行 —— ROS + Android 手机摄像头

    转载请注明出处,谢谢 原创作者:Mingrui 原创链接:https://www.cnblogs.com/MingruiYu/p/12404730.html 本文要点: ROS 配置安装 解决 sud ...

  2. mysql 存储过程 执行存储过程修改了表中所有行的信息

    存储过程中的where条件语句,如果传入的参数和表字段名相同,存储过程就会把这个约束条件忽略.小结:存储过程中传递的参数名不要和字段名相同.特别是修改.删除等操作,可能会对整张表产生影响.后果会很严重 ...

  3. 前端每日实战:31# 视频演示如何利用 CSS 的动画原理,创作一个乒乓球对打动画

    效果预览 按下右侧的"点击预览"按钮可以在当前页面预览,点击链接可以全屏预览. https://codepen.io/comehope/pen/rvgLzK 可交互视频教程 此视频 ...

  4. 微信小程序接入百度OCR(身份证识别)

    微信小程序接入百度OCR(身份证识别) 1.接口描述 支持对二代居民身份证正反面所有8个字段进行结构化识别,包括姓名.性别.民族.出生日期.住址.身份证号.签发机关.有效期限,识别准确率超过99%:同 ...

  5. 从String到==和hashcode

    public static void main(String[] args) { String s1 = "ni"; String s2 = "hao"; St ...

  6. spring boot 整合elasticsearch

    1.导入jar包 <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncodi ...

  7. IoT设备实践丨如果你也在树莓派上部署了k3s,你也许需要这篇文章

    前 言 树莓派是一种广泛流行的开发板,随着物联网的深入发展,树莓派大有成为IoT终端设备标准之趋势.在支持客户在IoT场景中落地k3s时,k3s在树莓派上的部署问题也就出现了.本文记录了一些其中的关键 ...

  8. WEB渗透 - XSS

    听说这个时间点是人类这种生物很重要的一个节点 cross-site scripting 跨站脚本漏洞 类型 存储型(持久) 反射型(非持久) DOM型 利用 先检测,看我们输入的内容是否有返回以及有无 ...

  9. Redis06——Redis到底能用在什么地方(上)

    之前我们介绍了一些列关于Redis的数据结构.持久化.过期&淘汰策略.集群化等知识点,感兴趣的小伙伴可以在文章的末尾查看往期内容.今天将为大家带来Redis的应用.由于本篇文章较长,所以将拆分 ...

  10. 今天对C语言不常用的小东西的了解

    今天又翻了C语言的书,看到const语句,一时间想不起来到底是干嘛的,看语句const   int   a=1;明白了这是一个支持常量指定类型的定义常量的关键字,作用几乎与#define一毛一样,但# ...