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