我正在0, 1, ..., (N - 1)按顺序依次读取数字。我的目标是仅使用O(1)空间来查找此给定排列的词典索引。
0, 1, ..., (N - 1)
O(1)
之前曾问过这个问题,但我能找到的所有算法都占用了O(N)空间。我开始认为这是不可能的。但这确实对减少分配数量有很大帮助。
O(N)
考虑以下数据:
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数和排列中的位数。
num_chars ^ num_perm_digits
num_chars
num_perm_digits
这需要O(1)空间,将初始清单视为恒定成本。并且需要O(N)时间,请考虑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; } }
这是一个伪代码,但转换为任何语言也很容易(: