Cantor Cantor Expand Expand & reverse
definition
Cantor expand to a full permutation is a natural number of two-shot , commonly used to build the hash table when space compression .
With \ (n-\) number \ ((1,2,3,4, \ DOTS, n-) \) , different compositions \ (n-! \) Permutations and combinations thereof, which is unique and expand a maximum of about Cantor \ (n! \)
Cantor Expand current arrangement is represented in the (n-\) \ whole arrangement of different elements in the ranking.
Time complexity \ (O (n ^ 2) \)
Scope
Searching, dynamic programming is often used to represent a number in a state greatly reduces the complexity of the space
official
\(X=a_1\times(n−1)!+a_2\times(n−2)!+⋯+a_n\times0!\)
\ (X \) on behalf of the whole arrangement arranged in the current rankings
\ (a_i \) representing the current number is the number of number sequences do not appear in the first few small starting count 0, the number 0 is the first small
For example $ 4,2,3, $ 1
\ (4 \) is the current number of number sequences do not appear in the section \ (3 \) small, \ (X-+ = 3 * (4-1)! \)
\ (2 \) is the number of the current number of columns do not appear in the first \ (1 \) small, \ (= 1 + X-* (4-2)! \)
\ (3 \) is the number of the current number of columns do not appear in the first \ (1 \) small, \ (X-+ = 1 * (4-3)! \) , Since \ (2 \) has been output over, so is not
\ (1 \) is the number of the current number of columns do not appear in the first \ (0 \) small, \ (the X-+ 0 = * (4-4)! \)
This can be determined the \ (4,2,3, 1 \) ranking uniquely corresponding to the full array of \ (X = 22 \)
- Note that every time we use to present in a small number of its number has not yet appeared
- Here count the number smaller than the number of its array appeared in a tree it is possible to optimize the \ (O (n \ log { n}) \)
Code
First pre-factorial
void init() {
fact[0] = 1;
for(int i = 1;i <= 9; ++i) fact[i] = fact[i - 1] * i;
// 递推求阶乘
}
\ (cantor \) function
int cantor(int a[],int n) {
bool st[10];// 标记数组
memset(st,0,sizeof st);
int res = 0;
for(int i = 0;i < n; ++i) {
int cnt = 0;
for(int j = 1;j < a[i]; ++j) if(!st[j]) cnt ++;
// 找到a[i]是当前数列中未出现的数中第几小的
st[a[i]] = 1;// 把这个数删掉
res += cnt * fact[n - i - 1];// 累加值
}
return res + 1;// 如果输出的是排名就要 + 1,如果是hash值可以直接返回 res
}
Inverse Cantor Expand
Because of the arrangement and the ranking arrangement it is one to one, so Cantor expand to meet the two-shot relationship, is reversible.
Similar to the above can be pushed back through the process down.
First, the ranking \ (X \) minus \ (1 \) , turn out to be \ (0 \) rankings began
E.g. seeking \ (1,2,3,4 \) a full permutation sequence, ranked \ (22 \) what sequence
\ (22--1 = 21 \) , \ (21 \) represents the number of permutations smaller than this arrangement
The first number \ (a [1] \)
\ (\ lfloor {21 / ( 4-1)!} \ rfloor = 3 \) than $ a [1] $ small and the number has not appeared \ (3 \) a, \ (A [. 1] =. 4 \)
\(X=X\mod3\times(4-1)!=3\)
The second number \ (a [2] \)
\ (\ lfloor {3 / ( 4-2)!} \ rfloor = 1 \) than \ (a [2] \) is small and the number has not appeared \ (1 \) a, so \ (a [2 ] = 2 \)
\(X=X\mod1\times(4-2)!=1\)
Third number \ (a [3] \)
\ (\ lfloor {1 / ( 4-3)!} \ rfloor = 1 \) than \ (a [3] \) for several hours and has not appeared \ (1 \) a, so \ (a [3 ] 3 = \)
\(X=X\mod1\times(4-3)!=0\)
The fourth number \ (a [4] \)
\ (\ lfloor {0 / ( 4-4)!} \ rfloor = 0 \) than \ (a [4] \) for several hours and has not appeared \ (0 \) a, so \ (a [4 ] = 1 \)
Finally get the number of columns \ (4,2,3,1 \)
Code
vector<int> incantor(int x,int n) {
x--;// 得到以0开始的排名
vector<int> res(n);// 保存数列答案
int cnt;
bool st[10];// 标记数组
memset(st,0,sizeof st);
for(int i = 0;i < n; ++i) {
cnt = x/fact[n - i - 1];// 比a[i]小且没有出现过的数的个数
x %= fact[n - i - 1];// 更新 x
for(int j = 1;j <= n; ++j) {// 找到a[i],从1开始向后找
if(st[j]) continue;// 如果被标记过,就跳过
if(!cnt) {// 如果cnt == 0说明当前数是a[i]
st[j] = 1;//标记
res[i] = j;// 第i位是j
break;
}
cnt --;// 如果当前不是0,就继续往后找
}
}
return res;// 返回答案
}