本文主要是介绍插入多少次发生哈希冲突:拉马努金Q分布与二元渐近分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
摘要: 拉马努金 Q 函数及其在算法分析中的应用【对算法,数学,计算机感兴趣的同学,欢迎关注我哈,原创文章】
我的网站:潮汐朝夕的生活实验室
我的公众号:算法题刷刷
我的知乎:潮汐朝夕
我的github:FennelDumplings
我的leetcode:FennelDumplings
各位好,本文我们继续讨论算法分析中的问题。
在哈希算法的分析中,哈希冲突是最受关注的问题。考虑有一个长度为 M M M 的数组作为哈希表存放数据的容器,然后一个一个地往里插入数据,假设哈希函数将每条数据随机地映射到 [ 1.. M ] [1..M] [1..M],问:在第一次哈希冲突发生之前,已经插入了多少条数据,记已插入数据的期望为 C M C_{M} CM。
首先给出结论,当 M → ∞ M\rightarrow\infty M→∞ 时,有:
C M = π M 2 + O ( 1 ) C_{M} = \sqrt{\frac{\pi M}{2}} + O(1) CM=2πM+O(1)
为了推导以上结论,需要用到拉马努金Q函数的相关结论。在上一篇文章 冒泡排序平均需要跑多少趟:拉马努金Q函数初探 中,我们接触到了拉马努金 Q 函数,但是并没有关注而是直接引用了相关结论。本文我们深入探讨一下。
拉马努金 Q 函数为一个和式,定义为 Q ( N ) = ∑ k = 1 N N ! ( N − k ) ! N k Q(N) = \sum\limits_{k=1}\limits^{N}\frac{N!}{(N-k)!N^{k}} Q(N)=k=1∑N(N−k)!NkN!,该和式中的被加项为关于 k 和 N 的二元函数 f ( k , N ) = N ! ( N − k ) ! N k f(k, N) = \frac{N!}{(N-k)!N^{k}} f(k,N)=(N−k)!NkN!。 Q ( N ) Q(N) Q(N) 的渐近分析结论的推导非常冗长,本文我们完成第一步,也就是对 f ( k , N ) f(k, N) f(k,N) 的渐近分析。
由于渐近分析的对象 f ( k , N ) f(k, N) f(k,N) 是个二元函数,因此我们处理的是二元渐进性的问题,而拉马努金 Q 分布是算法分析中处理二元渐进性的非常有代表性的例子,因此推导过程非常经典。以后遇到其它二元渐近分析的问题时,解决方案的框架类似。
有了 f ( k , N ) f(k, N) f(k,N) 的二元渐近分析结果, Q ( N ) Q(N) Q(N) 的渐近分析可以通过拉普拉斯方法得到,这一步的推导过程我们在以后介绍拉普拉斯方法的文章中再来完成,本文我们直接给出结果。然后基于该结果,立即就可以得到前面提到的关于哈希冲突问题的结论。
二元渐进性
在逼近和式的时候,经常会出现被加数既依赖于求和下标 k k k,又依赖于渐近增长的大小参数 N N N 的情况,也就是被加数是一个 k k k 和 N N N 的二元函数,类似于下面这样的和式:
∑ k = 0 N f ( k , N ) \sum\limits_{k=0}\limits^{N}f(k, N) k=0∑Nf(k,N)
f f f 中的 k k k 和 N N N 对以上和式的增长速度都很重要。例如,考虑 f ( k , N ) = k N k ! f(k, N) = \frac{k^{N}}{k!} f(k,N)=k!kN,当固定 k k k 时 f ( k , N ) f(k, N) f(k,N) 在 N → ∞ N\rightarrow\infty N→∞ 时以指数量级增大,当固定 N N N 时, f ( k , N ) f(k, N) f(k,N) 在 k → ∞ k\rightarrow\infty k→∞ 时以指数量级减小。这种情况下 N → ∞ N\rightarrow\infty N→∞ 时以上和式的渐近估阶就不容易了。
二项式系数 ( N k ) \binom{N}{k} (kN) 和拉马努金 Q 函数是在算法分析中最常见的二元函数,这两个函数的二元渐进性关系到很多算法的分析。本文我们看拉马努金 Q 函数的二元渐进性问题,二项式系数的二元渐进性问题以后我们再来看。
拉马努金 Q 分布
拉马努金 Q 分布最早由拉马努金研究,后来由于该分布在算法分析中有很多应用,Knuth 由对其进行了研究。该分布的公式为 f ( k , N ) = N ! ( N − k ) ! N k f(k, N) = \frac{N!}{(N-k)!N^{k}} f(k,N)=(N−k)!NkN!。
将以上分布对 k = 0 , 1 , ⋯ , N k=0,1,\cdots,N k=0,1,⋯,N 求和,就是拉马努金 Q 函数:
Q ( N ) = ∑ k = 1 N N ! ( N − k ) ! N k Q(N) = \sum\limits_{k=1}\limits^{N}\frac{N!}{(N-k)!N^{k}} Q(N)=k=1∑N(N−k)!NkN!
在概率论中,该函数也是我们熟知的生日函数:要找到具有相同生日的两个人, Q ( 365 ) + 1 Q(365) + 1 Q(365)+1 即为我们所需的期望试验次数。
为了估计 Q ( N ) Q(N) Q(N),首先要做的是在当 N → ∞ N\rightarrow \infty N→∞ 时,对所有 k k k 精确地估计出 f ( N , k ) f(N, k) f(N,k) 的值。首先给出定理结论如下,然后我们完整证明该定理,从证明过程中我们可以看到涉及到 k k k 和 N N N 两个变量的二元渐进性问题的讨论方式,这也是本文的核心内容。
定理(Ramanujan Q-分布)当 N → ∞ N\rightarrow\infty N→∞ 时,对于 k = o ( N 2 / 3 ) k = o(N^{2/3}) k=o(N2/3) 有相对误差界:
N ! ( N − k ) ! N k = e − k 2 2 N ( 1 + O ( k N ) + O ( k 3 N 2 ) ) \frac{N!}{(N-k)!N^{k}} = e^{-\frac{k^{2}}{2N}}(1 + O(\frac{k}{N}) + O(\frac{k^{3}}{N^{2}})) (N−k)!NkN!=e−2Nk2(1+O(Nk)+O(N2k3))
对于所有的 k k k,有绝对误差界:
N ! ( N − k ) ! N k = e − k 2 2 N + O ( 1 N ) \frac{N!}{(N-k)!N^{k}} = e^{-\frac{k^{2}}{2N}} + O(\frac{1}{\sqrt{N}}) (N−k)!NkN!=e−2Nk2+O(N1)
证明
首先处理 f ( k , N ) = N ! ( N − k ) ! N k f(k, N) = \frac{N!}{(N-k)!N^{k}} f(k,N)=(N−k)!NkN!:
N ! ( N − k ) ! N k = N ( N − 1 ) ( N − 2 ) ⋅ ⋅ ⋅ ( N − k + 1 ) N k = 1 ⋅ ( 1 − 1 N ) ( 1 − 2 N ) ⋅ ⋅ ⋅ ( 1 − N − ( k − 1 ) N ) = exp ( ln ( 1 − 1 N ) ( 1 − 2 N ) ⋅ ⋅ ⋅ ( 1 − N − ( k − 1 ) N ) ) = exp ( ∑ j = 1 k − 1 ln ( 1 − j N ) ) \begin{aligned} \frac{N!}{(N-k)!N^{k}} &= \frac{N(N-1)(N-2)\cdot\cdot\cdot(N-k+1)}{N^{k}} \\ &= 1\cdot(1 - \frac{1}{N})(1 - \frac{2}{N})\cdot\cdot\cdot(1 - \frac{N-(k-1)}{N}) \\ &= \exp(\ln(1 - \frac{1}{N})(1 - \frac{2}{N})\cdot\cdot\cdot(1 - \frac{N-(k-1)}{N})) \\ &= \exp(\sum\limits_{j=1}\limits^{k-1}\ln(1 - \frac{j}{N})) \\ \end{aligned} (N−k)!NkN!=NkN(N−1)(N−2)⋅⋅⋅(N−k+1)=1⋅(1−N1)(1−N2)⋅⋅⋅(1−NN−(k−1))=exp(ln(1−N1)(1−N2)⋅⋅⋅(1−NN−(k−1)))=exp(j=1∑k−1ln(1−Nj))
然后对于 k k k 与 N N N 不同的关系,分别分析。
对于 k = o ( N ) k =o(N) k=o(N),取 x = − j N , 1 ≤ j < k x = -\frac{j}{N}, 1 \leq j < k x=−Nj,1≤j<k,有 x → 0 x \rightarrow 0 x→0,因此由 ln ( 1 + x ) \ln(1 + x) ln(1+x) 在 x = 0 x = 0 x=0 的泰勒展开有:
ln ( 1 + x ) = x + O ( x 2 ) \ln(1 + x) = x + O(x^{2}) ln(1+x)=x+O(x2)
对 j = 1 , 2 , ⋯ , k − 1 j = 1,2,\cdots,k-1 j=1,2,⋯,k−1 求和,并应用自然数幂和公式后,得:
N ! ( N − k ) ! N k = exp ( ∑ j = 1 k − 1 ln ( 1 − j N ) ) = exp ( ∑ j = 1 k − 1 ( − j N + O ( j 2 N 2 ) ) ) = exp ( − k ( k − 1 ) 2 N + O ( k 3 N 2 ) ) \begin{aligned} \frac{N!}{(N-k)!N^{k}} &= \exp(\sum\limits_{j=1}\limits^{k-1}\ln(1 - \frac{j}{N})) \\ &= \exp(\sum\limits_{j=1}\limits^{k-1}(-\frac{j}{N} + O(\frac{j^{2}}{N^{2}}))) \\ &= \exp(-\frac{k(k-1)}{2N} + O(\frac{k^{3}}{N^{2}})) \end{aligned} (N−k)!NkN!=exp(j=1∑k−1ln(1−Nj))=exp(j=1∑k−1(−Nj+O(N2j2)))=exp(−2Nk(k−1)+O(N2k3))
进一步地,对于 k = o ( N 2 / 3 ) k = o(N^{2/3}) k=o(N2/3),有 k 2 N + O ( k 3 N 2 ) → 0 \frac{k}{2N} + O(\frac{k^{3}}{N^{2}}) \rightarrow 0 2Nk+O(N2k3)→0,因此由 e y e^{y} ey 在 y = 0 y = 0 y=0 的泰勒展开,得:
N ! ( N − k ) ! N k = exp ( − k ( k − 1 ) 2 N + O ( k 3 N 2 ) ) = exp ( − k 2 2 N ) exp ( k 2 N + O ( k 3 N 2 ) ) = e − k 2 2 N ( 1 + O ( k 2 N + O ( k 3 N 2 ) ) = e − k 2 2 N ( 1 + O ( k 2 N ) + O ( k 3 N 2 ) ) \begin{aligned} \frac{N!}{(N-k)!N^{k}} &= \exp(-\frac{k(k-1)}{2N} + O(\frac{k^{3}}{N^{2}})) \\ &= \exp(-\frac{k^{2}}{2N})\exp(\frac{k}{2N} + O(\frac{k^{3}}{N^{2}})) \\ &= e^{-\frac{k^{2}}{2N}}(1 + O(\frac{k}{2N} + O(\frac{k^{3}}{N^{2}})) \\ &= e^{-\frac{k^{2}}{2N}}(1 + O(\frac{k}{2N}) + O(\frac{k^{3}}{N^{2}})) \\ \end{aligned} (N−k)!NkN!=exp(−2Nk(k−1)+O(N2k3))=exp(−2Nk2)exp(2Nk+O(N2k3))=e−2Nk2(1+O(2Nk+O(N2k3))=e−2Nk2(1+O(2Nk)+O(N2k3))
其中最后一步用到大 O 符号的以下两条运算性质(参考潘承洞《阶的估计基础》):
- (1) O ( f + g ) = O ( f ) + O ( g ) O(f + g) = O(f) + O(g) O(f+g)=O(f)+O(g)
- (2) f ( x ) = O ( ϕ ) , ϕ = O ( ψ ) ⇒ f ( x ) = O ( ψ ) f(x) = O(\phi), \phi = O(\psi) \Rightarrow f(x) = O(\psi) f(x)=O(ϕ),ϕ=O(ψ)⇒f(x)=O(ψ)
于是就得到的定理的第一条关于相对误差界结论,当 k = o ( N 2 / 3 ) k = o(N^{2/3}) k=o(N2/3) 时有:
N ! ( N − k ) ! N k = e − k 2 2 N ( 1 + O ( k N ) + O ( k 3 N 2 ) ) \frac{N!}{(N-k)!N^{k}} = e^{-\frac{k^{2}}{2N}}(1 + O(\frac{k}{N}) + O(\frac{k^{3}}{N^{2}})) \\ (N−k)!NkN!=e−2Nk2(1+O(Nk)+O(N2k3))
这里需要注意,上式中两个大 O 项都应该保留,以便覆盖 k 值的范围。原因在于大 O 符号中同时有 k 和 N,对于 k 和 N 不同的关系,这两个大 O O O 哪个的阶更大是不知道的,例如:
- 仅有 O ( k 3 N 2 ) O(\frac{k^{3}}{N^{2}}) O(N2k3) 是不充分的,比如取 k = O ( 1 ) k = O(1) k=O(1), O ( k 3 N 2 ) O(\frac{k^{3}}{N^{2}}) O(N2k3) 的结果等于 O ( 1 N 2 ) O(\frac{1}{N^{2}}) O(N21),但 O ( k N ) O(\frac{k}{N}) O(Nk) 的结果是 O ( 1 N ) O(\frac{1}{N}) O(N1),更大。
- 仅有 O ( k N ) O(\frac{k}{N}) O(Nk) 也是不充分的,比如取 k = O ( N 3 5 ) k = O(N^{\frac{3}{5}}) k=O(N53), O ( k N ) O(\frac{k}{N}) O(Nk) 的结果等于 O ( 1 N 2 / 5 ) O(\frac{1}{N^{2/5}}) O(N2/51),但 O ( k 3 N 2 ) O(\frac{k^{3}}{N^{2}}) O(N2k3) 的结果是 O ( 1 N 1 / 5 ) O(\frac{1}{N^{1/5}}) O(N1/51),更大。
通过这个定理的推导,以及结果公式中两个大 O 项在 k 与 N 不同关系下谁的阶更大的讨论,我们认识到对于二元渐进性,必须要仔细处理。
下面推导定理的第二条关于绝对误差界的结论。
首先考虑 k 较小的情况,也就是 k ≤ k 0 k \leq k_{0} k≤k0,其中 k 0 k_{0} k0 稍小于 O ( N 2 / 3 ) O(N^{2/3}) O(N2/3),不妨取 k 0 = N 3 / 5 k_{0} = N^{3/5} k0=N3/5。这样就有 k = o ( N 2 / 3 ) k = o(N^{2/3}) k=o(N2/3),前面推导的相对误差界的结论可以用,因此有:
N ! ( N − k ) ! N k = e − k 2 2 N + e − k 2 2 N O ( k N ) + e − k 2 2 N O ( k 3 N 2 ) \frac{N!}{(N-k)!N^{k}} = e^{-\frac{k^{2}}{2N}} + e^{-\frac{k^{2}}{2N}}O(\frac{k}{N}) + e^{-\frac{k^{2}}{2N}}O(\frac{k^{3}}{N^{2}}) \\ (N−k)!NkN!=e−2Nk2+e−2Nk2O(Nk)+e−2Nk2O(N2k3)
记 x = k 2 N x = \frac{k}{\sqrt{2N}} x=2Nk,于是上式第二项可以写为 x e − x 2 O ( 1 N ) x e^{-x^{2}}O(\frac{1}{\sqrt{N}}) xe−x2O(N1),第三项可以写为 x 3 e − x 2 O ( 1 N ) x^{3}e^{-x^{2}}O(\frac{1}{\sqrt{N}}) x3e−x2O(N1)。
另一方面, x ≥ 0 x \geq 0 x≥0 时, x e − x 2 xe^{-x^{2}} xe−x2 以及 x 3 e − x 2 x^{3}e^{-x^{2}} x3e−x2 均有界,因此 x e − x 2 = O ( 1 ) xe^{-x^{2}} = O(1) xe−x2=O(1)、 x 3 e − x 2 = O ( 1 ) x^{3}e^{-x^{2}} = O(1) x3e−x2=O(1)。
N ! ( N − k ) ! N k = e − k 2 2 N + O ( 1 N ) \frac{N!}{(N-k)!N^{k}} = e^{-\frac{k^{2}}{2N}} + O(\frac{1}{\sqrt{N}}) (N−k)!NkN!=e−2Nk2+O(N1)
当 k 比较大时,即 k > k 1 k > k_{1} k>k1,其中 k 1 k_{1} k1 稍大于 N \sqrt{N} N 即可,还是不妨设 k 1 = N 3 / 5 k_{1} = N^{3/5} k1=N3/5。当 k = k 1 k = k_{1} k=k1 时,前面的结论仍然有效:
N ! ( N − k 1 ) ! N k 1 = e − N 1 / 5 2 + O ( 1 N ) \frac{N!}{(N-k_{1})!N^{k_{1}}} = e^{-\frac{N^{1/5}}{2}} + O(\frac{1}{\sqrt{N}}) (N−k1)!Nk1N!=e−2N1/5+O(N1)
上式中, e − N 1 / 5 2 e^{-\frac{N^{1/5}}{2}} e−2N1/5 是指数级的,且其系数随着 k 增加而减小,因此有 k ≥ k 1 k \geq k_{1} k≥k1 时,有:
N ! ( N − k ) ! N k = O ( 1 N ) \frac{N!}{(N-k)!N^{k}} = O(\frac{1}{\sqrt{N}}) (N−k)!NkN!=O(N1)
另一方面 k ≥ k 1 k \geq k_{1} k≥k1 时, e − k 2 2 N e^{-\frac{k^{2}}{2N}} e−2Nk2 也是指数级的(这里需要 k > N k > \sqrt{N} k>N),于是上式可以写为:
N ! ( N − k ) ! N k = e − k 2 2 N + O ( 1 N ) \frac{N!}{(N-k)!N^{k}} = e^{-\frac{k^{2}}{2N}} + O(\frac{1}{\sqrt{N}}) (N−k)!NkN!=e−2Nk2+O(N1)
综合上述 k 较小和 k 很大两方面,定理中第二部分的绝对误差界成立,即上式。
上述分析中,我们取了 k 0 = k 1 = N 3 / 5 k_{0} = k_{1} = N^{3/5} k0=k1=N3/5,这里的 k 0 = N 3 / 5 k_{0} = N^{3/5} k0=N3/5 的取值并不重要,它只需要足够小,使得相对误差界对 k < k 0 k < k_{0} k<k0 成立;同样地, k 1 = N 3 / 5 k_{1} = N^{3/5} k1=N3/5 的具体取值也不重要,它只需要足够大,使得对 k > k 1 k > k_{1} k>k1 时, e − k 2 2 N e^{-\frac{k^{2}}{2N}} e−2Nk2 为指数级的即可。
□ \Box □
有了上述拉马努金 Q 分布 f ( k , N ) = N ! ( N − k ) ! N k f(k, N) = \frac{N!}{(N-k)!N^{k}} f(k,N)=(N−k)!NkN! 的二元渐进性的分析,再结合使用拉普拉斯方法对和式的估计过程,可以得到拉马努金 Q 函数 Q ( N ) = ∑ k = 1 N f ( k , N ) Q(N) = \sum\limits_{k=1}\limits^{N}f(k, N) Q(N)=k=1∑Nf(k,N) 的渐近估阶。
在后续介绍拉普拉斯方法的文章中再来详细展开这一步的推导过程,这里我们直接给出结果: N → ∞ N\rightarrow \infty N→∞ 时, Q ( N ) = π N 2 + O ( 1 ) Q(N) = \sqrt{\frac{\pi N}{2}} + O(1) Q(N)=2πN+O(1)。
哈希冲突前平均已插入数据量
回到文章开头的问题。考虑有一个长度为 M M M 的数组作为哈希表存放数据的容器,然后一个一个地往里插入数据,假设哈希函数将每条数据随机地映射到 [ 1.. M ] [1..M] [1..M],问:在第一次哈希冲突发生之前,已经插入了多少条数据,记已插入数据的期望为 C M C_{M} CM。
第 1 次插入可以在 M M M 个位置中随便选,肯定不会发生冲突;第 2 次插入就有可能发生冲突了,冲突概率 1 M \frac{1}{M} M1;第 3 次插入时,数组中已有 2 哥位置被占了,此时插入,冲突的概率就变成了 2 M \frac{2}{M} M2。
以此类推,在第 N N N 次插入时,数组中已有 N − 1 N - 1 N−1 个位置被占,此时插入,冲突的概率就是 N − 1 M \frac{N-1}{M} MN−1。因此前 N N N 次插入均未发生冲突的概率为:
∏ k = 1 N ( 1 − k − 1 M ) = N ! M N ( M N ) \prod\limits_{k=1}\limits^{N}(1 - \frac{k-1}{M}) = \frac{N!}{M^{N}}\binom{M}{N} k=1∏N(1−Mk−1)=MNN!(NM)
记 X X X 表示第一次冲突前已插入的数据条数。上述概率给出的正是 P ( X ≥ N ) P(X \geq N) P(X≥N),由于数组长度为 M M M,因此当 k > M k > M k>M 时, P ( X ≥ k ) = 0 P(X \geq k) = 0 P(X≥k)=0,再由数学期望的性质,有:
C M = E ( X ) = ∑ k = 0 ∞ P ( X ≥ k ) = ∑ k = 0 M k ! M k ( M k ) = ∑ k = 0 M M ! M k ( M − k ) ! C_{M} = E(X) = \sum\limits_{k=0}\limits^{\infty}P(X \geq k) = \sum\limits_{k=0}\limits^{M}\frac{k!}{M^{k}}\binom{M}{k} = \sum\limits_{k=0}\limits^{M}\frac{M!}{M^{k}(M-k)!} CM=E(X)=k=0∑∞P(X≥k)=k=0∑MMkk!(kM)=k=0∑MMk(M−k)!M!
而拉马努金 Q 函数为 Q ( M ) = ∑ k = 1 M M ! M k ( M − k ) ! Q(M) = \sum\limits_{k=1}\limits^{M}\frac{M!}{M^{k}(M-k)!} Q(M)=k=1∑MMk(M−k)!M!,与上式相比仅求和范围少了 k = 0 k=0 k=0,因此结果就是 C M = 1 + Q ( M ) C_{M} = 1 + Q(M) CM=1+Q(M)。
由拉马努金 Q 函数的渐近估阶得到最终结果:
C M = 1 + Q ( M ) = π M 2 + O ( 1 ) C_{M} = 1 + Q(M) = \sqrt{\frac{\pi M}{2}} + O(1) CM=1+Q(M)=2πM+O(1)
总结
本文我们解决了第一次发生哈希冲突时,平均插入了多少数据的问题。其结果正是我们拉马努金 Q 函数 Q ( N ) Q(N) Q(N)。
Q ( N ) Q(N) Q(N) 是一个和式,具体为 Q ( N ) = ∑ k = 1 ∞ f ( k , N ) Q(N) = \sum\limits_{k=1}\limits^{\infty}f(k, N) Q(N)=k=1∑∞f(k,N),本文我们详细推导了 f ( k , N ) f(k, N) f(k,N) 的渐近估阶,其推导过程是处理二元渐进性非常有代表性的操作,有了这个例子,以后再遇到二元渐近分析的问题,思路可以仿照本例。
在此前解决冒泡排序平均扫描趟数的问题中,我们接触过拉马努金 Q 函数 Q ( N ) Q(N) Q(N),当时我们直接使用了 Q ( N ) Q(N) Q(N) 的渐近估阶的结论。本文我们前进了一步,完成了 Q ( N ) Q(N) Q(N) 中的被加项 f ( k , N ) f(k, N) f(k,N) 的二元渐近分析。
至此拉马努金 Q 函数 Q ( N ) Q(N) Q(N) 的渐近估阶就完成了一半,后续的分析用到了拉普拉斯方法,这也是渐近分析的一个经典手法,后续再跟大家探讨。
这篇关于插入多少次发生哈希冲突:拉马努金Q分布与二元渐近分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!