找到给定排列的索引

Mug*_*gen 7 algorithm space permutation combinatorics

我正在0, 1, ..., (N - 1)按顺序逐个阅读这些数字.我的目标是只使用O(1)空格来找到这个给定排列的词典编纂索引.

之前曾问过这个问题,但我能找到的所有算法都使用了O(N)空间.我开始认为这是不可能的.但是,通过减少分配数量,这对我帮助很大.

Rub*_*ens 4

考虑以下数据:

chars = [a, b, c, d]
perm = [c, d, a, b]
ids = get_indexes(perm, chars) = [2, 3, 0, 1]
Run Code Online (Sandbox Code Playgroud)

具有重复的排列的可能解决方案如下:

len = length(perm)         (len = 4)
num_chars = length(chars)  (len = 4)

base = num_chars ^ len     (base = 4 ^ 4 = 256)
base = base / len          (base = 256 / 4 = 64)

id = base * ids[0]         (id = 64 * 2 = 128)
base = base / len          (base = 64 / 4 = 16)

id = id + (base * ids[1])  (id = 128 + (16 * 3) = 176)
base = base / len          (base = 16 / 4 = 4)

id = id + (base * ids[2])  (id = 176 + (4 * 0) = 176)
base = base / len          (base = 4 / 4 = 1)

id = id + (base * ids[3])  (id = 176 + (1 * 1) = 177)
Run Code Online (Sandbox Code Playgroud)

逆过程:

id = 177
(id / (4 ^ 3)) % 4 = (177 / 64) % 4 =   2 % 4 = 2 -> chars[2] -> c
(id / (4 ^ 2)) % 4 = (177 / 16) % 4 =  11 % 4 = 3 -> chars[3] -> d
(id / (4 ^ 1)) % 4 = (177 / 4)  % 4 =  44 % 4 = 0 -> chars[0] -> a
(id / (4 ^ 0)) % 4 = (177 / 1)  % 4 = 177 % 4 = 1 -> chars[1] -> b
Run Code Online (Sandbox Code Playgroud)

可能的排列数由 给出num_chars ^ num_perm_digits,其中num_chars为可能的字符数,num_perm_digits为排列中的位数。

这需要O(1)在空间上,将初始列表视为恒定成本;并且它需要O(N)时间,考虑N到您的排列将具有的位数。

根据上述步骤,您可以执行以下操作:

function identify_permutation(perm, chars) {

    for (i = 0; i < length(perm); i++) {
        ids[i] = get_index(perm[i], chars);
    }

    len = length(perm);
    num_chars = length(chars);

    index = 0;
    base = num_chars ^ len - 1;
    base = base / len;
    for (i = 0; i < length(perm); i++) {
        index += base * ids[i];
        base = base / len;
    }

}
Run Code Online (Sandbox Code Playgroud)

这是一个伪代码,但也很容易转换为任何语言(: