Cantor Cantor Expand Expand & reverse

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;// 返回答案
}

Guess you like

Origin www.cnblogs.com/lukelmouse/p/12443311.html