康托展開原理

2021-09-10 16:08:35 字數 1205 閱讀 3207

康托展開結合組合數學會比較容易理解。

假設有  這三個數,那麼全部的排列組合有 6種,按從小到大的順序有 123, 132,213, 231, 312, 321。

而康託展開能以n^2的時間複雜度求出比某個排序組合小的個數。比如說 比 213 小的數有2個,比312小的數有4個。

原理:假設有  這4個數,根據組合數學的知識,一共有 4*3*2*1種排序組合。

3***,這種排序組合且比這種排序組合都小的個數有多少?很明顯是 3*3!。

34**,這種排序組合且比這種排序組合都小的個數有多少? 2*3!+ 3*2!。

等式包含兩大類,一類是比34**所有組合都小的,即以1為首和以2為首的所有組合 2*3!,還有31**, 32**的所有組合 2*2!。另一類是34**的所有組合 2!。

同樣的,342*,這種排序組合且比這種排序組合都小的個數有多少?比342*都小的分別有 1***,2***,31**,32**,341*,即2*3!+2*2!+1!,而342*這種組合有 1!。一共有2*3!+2*2!+2*1!。

對於3421這種排序組合,我們只求比這種排序組合小的個數有多少,總結上面的內容,比3421小的組合有1***,2***,31**,32**,341*,即 2*3!+2*2!+1*1!。

根據上面所講的,康托展開的原理就是從某個排序組合的首位開始,找出比當前這位數小的個數,且之前沒有出現過的數的個數乘以對應的階乘,結果累加就是我們要求的值。

比如說3421,從首位3開始,比3小的之前沒出現過的數有1,2,那麼就有 2*3!。

第二位是4,比4小的數有1,2,3,但是3已經出現在首位了,所以總共只有2個,即1,2,那麼就有2*2!。

第三位是2,比2小的數有只有1,而且首位和第二位都不是1,那麼就有1*1!。

通過這種方法就能很快的求出比某個排序組合小的總個數。

這種技巧也能夠運用在狀態壓縮上面,某個排序組合有 x個比它小的排序組合,那麼可以給這種排序組合編號為x,可以保證不會有編號重疊的情況,實現符號壓縮。

在已知編號的情況下,也能夠通過編號還原排列組合。順序反過來就行了。

int cantor(char* ss) 

ret += cnt*n[8-i];

}return ret;

}void decantor(int num, char *ss)

cnt++;}}

ss[p] = '\0';

}

康托展開 康托逆展開

x a n n 1 a n 1 n 2 a i i 1 a 1 0 其中a i 為當前未出現的元素中是排在第幾個 從0開始 這就是康托展開。康托展開可用 實現。編輯 把乙個整數x展開成如下形式 x a n n 1 a n 1 n 2 a i i 1 a 2 1 a 1 0 其中a i 為當前未出現的...

康托展開 逆康托展開

康托展開 問題 給定的全排列,計算出它是第幾個排列 求序列號 方法 康托展開 對於乙個長度為 n 的排列 num 1 n 其序列號 x 為 x a 1 n i a 2 n 2 a i n i a n 1 1 a n 0 其中a i 表示在num i 1 n 中比num i 小的數的數量 includ...

康托展開 逆康托展開

用途 康托展開是一種雙射,用於排列和整數之間的對映,可用於排列的雜湊 康托展開 公式 i n1pi i 1 sum limits p i i 1 i n 1 pi i 1 其中p ip i pi 為第i ii個數構成的逆序的個數,n為排列數的個數 例 排列 2134 i n1pi i 1 sum l...