康拓展開在全排列中的應用

2021-10-24 08:49:05 字數 2066 閱讀 4369

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

第k個排列給出乙個數n,返回第k個排列。

假設n=3,k=3.那麼第三個排列就是213

不難發現,當n=1的時候,有乙個排列。11

當n=2的時候,有兩個排列。12和21。21

當n=3的時候,根據上圖可知有6種排列。321

可得:1…n有n!種排列。

相同的,當n=5的時候,求52413是第幾個排列。

public static void main(string args) 

//階乘結果陣列

static int arr = new int;

//計算某數字在多少位

//52413

public static int calculaterank(int num)

}//小的數字個數x後面的空格數的階乘

//第0位後面有: 5 - 0 -1 = 4 個空位

res += cnt * arr[len - i -1];

}return res+1;

}

既然康拓展開可以求某數字是全排列是多少位,那麼顧名思義逆康拓展開可以求第幾位全排列的數字具體的值。

同理求107在全排列結果集中對應的數字。

由於康拓展開從0開始,所以第107個對應的是106.

同樣的給出1…5,求107對應的全排列數字。

//階乘結果陣列

//記錄是否使用過

used = new boolean[n];

listlist = new arraylist<>();

return dfs(list,0,n,k);

}private string dfs(listlevellist, int level, int n, int k)

return res.tostring();

}//比如來到了確定第一位的數字 我們假設n=5 確定一位有 (5 - 0 -1 )! 種情況

int curcount = factorial(n - level - 1);

//組合每一位 我這裡是按照索引取值

for (int i = 0; i < n; i++)

if (curcount < k)

//剩下的就是確定結果的時候啦

levellist.add(nums[i]+"");

used[i] = true;

//在以往的回溯中 會把標記還原 但是此處不同,因為我們直接確定的就是最後一層

return dfs(levellist,level+1,n,k);

}return null;

}private int factorial(int n)

return res;}}

此外,康托展開也是乙個陣列到乙個數的對映,可以應用於hash中進行空間壓縮。例如,在八數碼問題中,我們可以把一種排列狀態壓縮成乙個整數存放在陣列中。

康托展開在全排列中使用(C 實現)

在乙個全排列中,比如在1,2,3,4,5所有的全排列中,如何確定34152在1,2,3,4,5所欲排列中排第幾?康托展開的公式為以1,2,3,4,5為例,那麼康托展開的公式為 x a 5 5 1 a 4 4 1 a 3 3 1 a 2 2 1 a 1 1 1 其中1 a i 5,a i 表示 從首位...

康托展開 全排列

今天找到了一篇非常好的介紹康托展開的文章!其核心是這一張圖 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,那...