小编典典

查找给定排列的索引

algorithm

我正在0, 1, ..., (N - 1)按顺序依次读取数字。我的目标是仅使用O(1)空间来查找此给定排列的词典索引。

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


阅读 268

收藏
2020-07-28

共1个答案

小编典典

考虑以下数据:

chars = [a, b, c, d]
perm = [c, d, a, b]
ids = get_indexes(perm, chars) = [2, 3, 0, 1]

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

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)

逆向过程:

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

可能的排列数由给出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;
    for (i = 0; i < length(perm); i++) {
        index += base * ids[i];
        base = base / len;
    }

}

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

2020-07-28