《Mathematical Analysis of Algorithms》中有關「就地排列」(In Situ Permutation)的算法分析

問題描述

把數列\((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)\).c++

算法描述

對於映射\(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) \]

咱們能夠觀察到這樣的規律:spa

\[\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)\)的額外空間完成數字的交換。而這個交換咱們從每一個圈中的最小數開始作。code

代碼描述:
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)的距離之和
 */
最壞狀況

最壞的狀況以下class

\[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\)的最壞狀況。im

b的平均值分析

對於上面引用的\(p\)的實例:di

\[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)\)

相關文章
相關標籤/搜索