MIT 6.1220 — Lecture 7

Hash Functions (Part II)

Here's another way to handle key collisions.

Solution. (Open Addressing) Every key k∈Uk \in \mathcal{U} is assigned not just one hash value in {0,1,…,m−1}\{0, 1, \dots, m - 1\}, but rather a permutation of {0,1,…,m−1}\{0, 1, \dots, m - 1\} called a probing sequence:

h:U×{0,1,…,m−1}→{0,1,…,m−1}  such that  k  has probing sequence (h(k,0),h(k,1),…,h(k,m−1)).h: \mathcal{U} \times \{0, 1, \dots, m - 1\} \to \{0, 1, \dots, m- 1\} ~ \text{ such that } ~ k ~ \text{ has probing sequence } (h(k, 0), h(k, 1), \dots, h(k, m - 1)).

We implement our desired operations as follows:

Remark. Some CYU questions:

Claim. Suppose that every key receives an independently generated uniformly random sequence.

Then the expected number of pp we will need to check is O(11−α)O\left(\frac{1}{1 - \alpha}\right), where α:=nm<1\alpha := \frac{n}{m} < 1.

Proof: Handwaving… a guess for pp succeeds with probability 1−α1 - \alpha, so the EV # of tries is 11−α\frac{1}{1 - \alpha}.   ■\blacksquare

The rigorous proof goes Eh[X]=∑j=1mj⋅Prh[X=j]=∑j=1mPrh[X≥j]≤∑j=1mαj−1≤11−α\underset{h}{\mathbb{E}}[X] = \displaystyle\sum_{j = 1}^m j \cdot \underset{h}{\mathrm{Pr}}[X = j] = \displaystyle \sum_{j = 1}^m \underset{h}{\mathrm{Pr}}[X \geq j] \leq \displaystyle\sum_{j = 1}^m \alpha^{j - 1} \leq \frac{1}{1 - \alpha}, hooray.   ■\blacksquare

Even more formally, we need to justify Prh[X≥j]≤αj−1\underset{h}{\mathrm{Pr}}[X \geq j] \leq \alpha^{j - 1}, so we should be writing something like the following, where EiE_i is the event that the ithi^{\text{th}} probe finds an occupied slot:

Prh[X≥j]=Prh[E1∧E2∧⋯∧Ej−1]=Prh[E1]×Prh[E2∣E1]×⋯×Prh[Ej−1∣E1∧E2∧⋯∧Ej−2].\underset{h}{\mathrm{Pr}}[X \geq j] = \underset{h}{\mathrm{Pr}}[E_1 \wedge E_2 \wedge \dots \wedge E_{j - 1}] = \underset{h}{\mathrm{Pr}}[E_1] \times \underset{h}{\mathrm{Pr}}[E_2 \mid E_1] \times \dots \times \underset{h}{\mathrm{Pr}}[E_{j - 1} \mid E_1 \wedge E_2 \wedge \dots \wedge E_{j - 2}].

And the ℓth\ell^{\text{th}} term in this product is upper-bounded by n−ℓ+1m−ℓ+1≤nm=α\frac{n - \ell + 1}{m - \ell + 1} \leq \frac{n}{m} = \alpha, as desired.   ■\blacksquare

Generating probing sequences uniformly at random is hard, so in practice, we implement like so.

Solution. (Probing Methods) Pick any two hash functions h1,h2:U→{0,1,…,m−1}h_1, h_2: \mathcal{U} \to \{0, 1, \dots, m - 1\}. We can use:

Now for something new. Let's try to implement…

Problem. (Static Dictionaries & Perfect Hashing) We are given {(k1,v1),…,(kn,vn)}\{(k_1, v_1), \dots, (k_n, v_n)\} up front, after which point only Search(k)\textsc{Search}(k) may be called. We would like the following:

Expected Pre-Processing Time: O(n)  ∣  Space: O(n)  ∣  Search Operations: O(1) always\text{Expected Pre-Processing Time: } O(n) ~~ \mid ~~ \text{Space: } O(n) ~~ \mid ~~ \text{Search Operations: } O(1) \text{ always}

In particular, we require perfect hashing: no collisions occur at all!

Here's a naive solution that passes all constraints except the space requirement.

Solution. (Suboptimal-Space Solution) Consider a universal hash family H\mathcal{H}, and take m≥n2m \geq n^2.

Then pick h∈Hh \in \mathcal{H}, and use ki↦h(ki)k_i \mapsto h(k_i). If the first h∈Hh \in \mathcal{H} fails, pick another h∼Hh \sim \mathcal{H} until success.

Proof: This works in expected O(n)O(n) pre-processing time because Prh∼H[no collisions]≥12\underset{h \sim \mathcal{H}}{\mathrm{Pr}}[\text{no collisions}] \geq \frac{1}{2} by Union Bound—try it yourself! (When does universality of H\mathcal{H} get used?)   ■\blacksquare

Here's the smart solution by Fredman-Komlos-Szemeredi (1984) that passes the space requirement.

Solution. (Optimal-Space Solution) Sample a hash function h1∈H1h_1 \in \mathcal{H}_1 that goes h1:U→{0,1,…,n−1}h_1: \mathcal{U} \to \{0, 1, \dots, n - 1\}.

Our data structure is then a two-dimensional array: nn buckets, the ℓth\ell^{\text{th}} of which has Nℓ2N_{\ell}^2 slots to hash into.

Proof: It's easy to see that this has O(1)O(1) search time, and that we only need O(n)O(n) pre-processing time once h1h_1 is chosen.

The hard part is achieving O(n)O(n) space. If we choose h1h_1 unluckily, we won't actually get O(n)O(n) space! However,

Claim.     Prh∼H1[(∑ℓ=0n−1Nℓ2)>4n]<12.\textbf{Claim.} ~~~~~ \underset{h \sim \mathcal{H}_1}{\mathrm{Pr}} \left [ \left(\sum_{\ell = 0}^{n - 1} N_{\ell}^2\right) > 4n \right ] < \dfrac{1}{2}.

To prove this, note that by Markov's inequality, it suffices to show Eh∼H1[∑ℓ=0n−1Nℓ2]<2n\underset{h \sim \mathcal{H}_1}{\mathbb{E}}\left [ \sum_{\ell = 0}^{n - 1} N_{\ell}^2 \right ] < 2n. This takes some clever work:

Eh∼H1[∑ℓ=0n−1Nℓ2]= Eh∼H1[∑ℓ=0n−1(Nℓ+∑j≠j′1[h(kj)=h(kj′)=ℓ])]= Eh∼H1[∑ℓ=0n−1Nℓ]+Eh∼H1[∑ℓ=0n−1∑j≠j′1[h(kj)=h(kj′)=ℓ]]= n+∑j≠j′(Prh∼H1[h(kj)=h(kj′)])≤ n+n(n−1)n<2n.\begin{align*}\underset{h \sim \mathcal{H}_1}{\mathbb{E}} \left [ \sum_{\ell = 0}^{n - 1} N_{\ell}^2 \right ] = \ & \underset{h \sim \mathcal{H}_1}{\mathbb{E}} \left [ \sum_{\ell = 0}^{n - 1} \left ( N_{\ell} + \sum_{j \neq j'} \mathds{1}\left [ h(k_j) = h(k_{j'}) = \ell \right ] \right ) \right ] \\ = \ & \underset{h \sim \mathcal{H}_1}{\mathbb{E}}\left [ \sum_{\ell = 0}^{n - 1} N_{\ell} \right ] + \underset{h \sim \mathcal{H}_1}{\mathbb{E}} \left [ \sum_{\ell = 0}^{n - 1} \sum_{j \neq j'} \mathds{1}\left [ h(k_j) = h(k_{j'}) = \ell \right ] \right ] \\ = \ & n + \sum_{j \neq j'} \left(\underset{h \sim \mathcal{H}_1}{\mathrm{Pr}}[h(k_j) = h(k_{j'})] \right) \\ \leq \ & n + \frac{n(n - 1)}{n} < 2n.\end{align*}

Thus, we can guarantee O(n)O(n) space in expected O(n)O(n) time by repeatedly resampling h1h_1 until the space is less than 4n4n.   ■\blacksquare