全排列 康托展開

2022-08-20 12:03:08 字數 1197 閱讀 5033

#includeusing

namespace

std;

int num[100

],cnt;

void fun(int pos,int

n);int judge(int l,int

r);int

main()

int judge(int l,int

r)void fun(int pos,int

n)

for(int i=pos;i<=n;i++) }

康托展開是乙個全排列到乙個自然數的雙射,常用於構建雜湊表時的空間壓縮。 康托展開的實質是計算當前排列在所有由小到大全排列中的順序,因此是可逆的。

令x為全排列中的次序,num為原陣列,n為全排列中數字的個數,

為num[j] (j>i)小於num[i]的個數。

則例:有(1,2,3,4,5)5個數的全排列中,計算34152的康托展開值。

通過定義可知,a[5] = 2 (1<3,2<3),a[4] = 2 (1<4,2<4),a[3] = 0 (無),a[2] = 1 (2<5),a[1] = 0 (無)。

又因為 n = 5,則x=2*4! + 2*3! + 0*2! + 1*1! + 0*0! = 61

所以在全排列中比34152小的有61個,即34152在全排列中排第62位(61+1=62)。

因為康托展開是乙個全排列到乙個自然數的雙射,所以可以通過61計算出34152。

有,得出

例:61/4! = 2...13  則a[5] = 2,num[5]=3

13/3! = 2...1  則a[5] = 2,num[4]=4

1/2! = 0...1  則a[5] = 0,num[4]=1

1/1! = 1...0  則a[5] = 1,num[2]=5

則num[1]為剩下的數,num[1]=2

所以前面有61個排列,即第62個全排列為34152。

26458173的下乙個全排列為26458317。

步驟:①從後往前找到第乙個

的位置 (即樣例中為1<7)

②從後往前找到第乙個大於

的數 x ,交換

和 x的位置 (

=1,x=3),得到26458371

③將位置 i 以後的數反轉,得到26458317。

上乙個全排列的求法與下乙個全排列類似,自行解決。

康托展開 全排列

今天找到了一篇非常好的介紹康托展開的文章!其核心是這一張圖 letter 儲存所需字母表 void initletter 初始化字母表 int fact int n 階乘 return result void output vector v 輸出生成的結果 cout endl void divisi...

康托展開 全排列

對於n個數的全排列,共有n!中排列方式,如何求某乙個序列在整個排列中的次序 從小到大 以9的全排枚舉例 842697513是1 9全排列的第幾個?高中數學排列組合問題,只需要做到不重不漏 首先看第一位為8,那麼第一位為1 7的全排列都比它小,共有7 8!個。在第一位為8的情況下,其次看第二位為4,那...

全排列康托展開

n個元素有n 個不同的排列。將這n 個排列按字典序排列,並編號為0,1,n 1。每個排列的編號為其字典序值。例如,當n 3時,6 個不同排列的字典序值如下 0 1 2 3 4 5 123 132 213 231 312 321 任務 給定n 以及n 個元素的乙個排列,計算出這個排列的字典序值,以及按...