康托展開和逆展開

2022-08-24 21:30:12 字數 1305 閱讀 4004

康托展開:

給定乙個排列(由n個數排列而成),我們可以計算出該排列在由n個數組成的所有排列中排名第幾(按字典序),這就是康托展開。

比如由4個數1,2,3,4組成排列

那麼2413在所有的排列中排第幾呢?

首先計算第一位數字比2小的排列有多少種,即 1 * fac[3],怎麼得來的呢?首先比2小的數字只有1個,那麼第一位數字只有一種選擇,剩下的三位數字有fac[3]種選擇,所以是1 * fac[3]

現在當第一位固定是2,那麼來計算第二位數字比4小的排列有多少種呢?首先比4小的數字有1個,那麼第一位數字只有一種選擇,剩下的兩位數字有fac[2]中選擇,所以是1*fac[2]

依次類推,當前兩位固定為24,第三位比1小的排列有0 * fac[1]

以此類推,當前兩三位固定為241時,第4位比3小的排列有0*fac[0];

即fac[3] + fac[2] = 8;特別記住,我們算出來的是比2413小的排列有多少種,所以2413在所有由1,2,3,4組成的排列中排名第9。

1

int kt(int *a, int n)//

算出陣列中儲存的數字在全排列中排第幾

2

12return pos + 1

;13 }

view code

康托逆展開:

給定5個數1,2,3,4,5,  找出排第48的排列是什麼,設這個排列為x1x2x3x4x5,

設比x1小的數字有k1個,那麼有k1*4!種排列比x1x2x3x4x5小

設比x2小的數字有k2個,那麼有k2*3!種排列比x1x2x3x4x5小。

以此類推,共有k1*4!+k2*3!+k3*2!+k4*1!種階乘比x1x2x3x4x5小

即k1*4!+k2*3!+k3*2!+k4*1!==48-1

而且,k1<=4, k2<=3,k3<=2,k4<=1.那麼即使k2,k3,k3取最大值,即k2=3,k3=2,k4=1

那麼k2*3!+k3*2!+k4*1! 依舊<4!   所以可以用47/4!得到k1

然後 (47-k1*4!) / 3!  得到k2,

以此類推得到k3,k4

1/*2

算出由陣列中存的n個不同的數組成的排第pos位的排列是什麼3*/

4void kt_decode(int *a, int *b,int pos, intn)5

24} 25}

26for(j=0; jj)

27if(!vis[a[j]])

28 b[i++] =a[j];

2930 }

康托展開和逆康托展開

為什麼我在en wiki上查不到啊tat 嗯,康托展開就是乙個從n排列集合到自然數集合的對映.並且這個對映剛好對應了字典序.比如,設這個函式為c,那麼c 0,c 5,c 3.用於排列與數字的轉換.使用的時候一定要注意先把排列離散化成0,1,n 1的排列再做.否則要用n 2的時間來找 在全集中比數i小...

康托展開和康托逆展開

x a n n 1 a n 1 n 2 a i i 1 a 1 0 其中,a i 為整數,並且x a n n 1 a n 1 n 2 a i i 1 a 1 0 這就是康托展開。1324是排列數中第幾個大的數 第一位是1小於1的數沒有,是0個,0 3 第二位是3小於3的數有1和2,但1已經在第一位了...

康托展開和逆康托展開

康托展開是乙個全排列到乙個自然數的雙射,常用於構建hash表時的空間壓縮。設有n個數 1,2,3,4,n 可以有組成不同 n 種 的排列組合,康托展開表示的就是是當前排列組合在n個不同元素的全排列中的名次。x a n n 1 a n 1 n 2 a i i 1 a 1 0 其中,a i 為整數,並且...