哈希函数和随机排列

Hash functions and random permutation

本文关键字:排列 随机 函数 哈希      更新时间:2023-10-16

看完这个问题。我想知道是否可以使用 O(1) 空间来生成序列 [1...n] 的随机排列,并使用双哈希之类的东西进行均匀分布?

我用序列 [1,2,3,4,5] 的一个小例子尝试了这个,它有效。但是对于较大的集合,它无法缩放。

int h1(int k) {
    return 5 - (k % 7);
}
int h2(int k) {
    return (k % 3) + 1;
}
int hash(int k, int i) {
    return (h1(k) + i*h2(k)) % size;
}
int main() {
    for(int k = 0; k < 10; k++) {
        std::cout << "k=" << k <<  std::endl;
        for(int i = 0; i < 5; i++) {
            int q = hash(k, i);
            if(q < 0) q += 5;
            std::cout << q;
        }
        std::cout << std::endl;
    }
}

您可以尝试另一种方法。

  1. 取任意整数 P,GCD(P, N) == 1其中GCD(P, N)PN的最大公约数(例如 GCD(70, 42) == 14GCD(24, 35) == 1 )。
  2. 获取序列K[i] ::= (P * i) mod N + 1,从1N i
  3. 事实证明,序列 K[i] 枚举了1 和 N 没有重复(实际上是K[N + 1] == K[1]但这不是问题,因为我们只需要前 N 个数字)。

如果你能有效地生成这样的数字,P均匀分布(例如,使用良好的随机函数),使用欧几里得算法计算 O(log(N)) 复杂度的 GCD,你就会得到你想要的。

如果没有一些随机性,就不可能生成"随机"排列。 这甚至没有意义。 您的代码每次都会生成相同的排列。

我怀疑你打算每次都选择不同的两个随机哈希函数。 但即使这样使用哈希函数也不起作用,就像你所拥有的(a +/- k%b随机选择的a,b),因为你需要O(n log n)位随机性来指定排列。

我不确定问题是什么。 如果你想要一个随机排列,你想要一个随机数生成器,而不是一个哈希函数。 哈希函数是(并且必须是)确定性的,因此它不能用于"随机"排列。 哈希不是任何东西的排列。

我不认为随机排列可以是 O(1) 空间。 你有以某种方式跟踪已经使用的元素。