# Find two numbers in array $A$ such that $|x-y| \leq \frac{\max(A)-\min(A)}n$ in linear time

I'm struggling with the following question:

Let $$\langle a_0, a_1,\dots,a_n\rangle$$ be a sequence of real numbers, and let $$M = \max\{a_0, a_1, .... a_n\}$$ and $$m = \min\{a_0, a_1, .... a_n\}$$.

a. Prove that there are two numbers in the sequence $$x,y$$ such that $$|x-y| \leq \frac{M-m}n$$.

b. Write an algorithm that finds those numbers in linear time.

I've manage to prove part a, but am struggling with part b. I've tried to find a way to find the two element in the array that have the smallest difference, but couldn't find a way to do it in $$\Theta(n)$$. It should be something related to select algorithm and medians.

This is an interesting question.

Here is a linear-time algorithm. Assum $$n\ge1$$.

1. Compute the minimum $$m$$ and the maximum $$M$$. If $$m=M$$, return $$a_0$$ and $$a_1$$. Otherwise, let $$\delta=\frac{M-m}n$$.
2. For $$i$$ from $$0$$ to $$n$$, let $$\text{slot}_i$$ be an empty list of numbers.
3. For $$i$$ from $$0$$ to $$n$$, append $$a_i$$ to $$\text{slot}_{\lfloor (a_i-m)/\delta\rfloor}$$.
4. For $$i$$ from $$0$$ to $$n$$, check whether there are at least two numbers in $$\text{slot}_i$$. If yes, return any two numbers in $$\text{slot}_i$$.
5. Otherwise, each $$\text{slot}$$ contains one number. For $$i$$ from $$1$$ to $$n$$, check whether $$b_{i}-b_{i-1}\le \delta$$, where $$b_{j}$$ is the only number in $$\text{slot}_j$$. If yes, return $$b_{i-1}$$ and $$b_{i}$$.

It is easy to see the algorithm is correct with time-complexity $$\Theta(n)$$.

It might be interesting how I found my initial algorithm.

I literally recited George Pólya's principle, "do you know a similar problem?". I recalled that finding duplicate elements in an array using hash table takes linear time of $$n$$. Could I apply that conclusion? Or the way of using hash table? What is a hash table and how can I create a hash here? If I can put nearby numbers in the same slot, I can considered them as the same, then the algorithm might work. The it dawned on me that I could use the location of $$a_j$$ as "its hash". However, two numbers that are very close could be mapped to different hashes, which breaks the promise. If one hash is not enough, how about two hashes? I could almost see the light on the other side of the tunnel. After a few minor adjustments, I arrived at my initial algorithm.

(Somehow I missed Yuval's nice algorithm by divide and conquer, which, in hindsight, should not have been difficult to find.)

Let $$z$$ be the median of $$A$$, and split $$A$$ into two subarrays $$B,C$$: the array $$B$$ consists of all numbers at most $$z$$ (including $$z$$), and the array $$C$$ consists of all number at least $$z$$ (including $$z$$). Assuming for simplicity that $$n$$ is even and that all elements in $$A$$ are distinct, we can write $$B = b_0,\ldots,b_{n/2}, \\ C = c_0,\ldots,c_{n/2},$$ where $$b_{n/2} = c_0 = z$$. Define $$\delta(X) = \frac{\max(X) - \min(X)}{\mathrm{len}(X)-1}$$. Then $$\delta(B) + \delta(C) = \frac{z-\min(A)}{n/2} + \frac{\max(A)-z}{n/2} = \frac{\max(A)-\min(A)}{n/2} = 2\delta(A),$$ and so $$\min(\delta(B),\delta(C)) \leq \delta(A)$$. This implies that we can recurse on either $$B$$ or $$C$$.

Using a linear time algorithm for finding the median, we obtain an algorithm whose running time satisfies the recurrence $$T(n) = T(n/2) + \Theta(n)$$, whose solution is $$T(n) = \Theta(n)$$. Details left to you.

Let me comment that $$\min(\delta(B),\delta(C)) \leq \delta(A)$$ whatever the sizes of $$B,C$$ are (this requires a simple adaptation of the above proof). This suggest a randomized algorithm running in expected linear time, which simply chooses $$z$$ at random. This is possibly more efficient in practice.

Find the minimum m and M; m = M is trivial.

For each i, let yi = (xi - m) * n / (M - m), so 0 <= yi <= n. Start with an empty table with entries 0 to n, then for each i record i and yi at entry floor(yi). When you find i and j using the same entry, then xi and xj are close enough together. If you don't find i and j, then all values floor(yi) are unique. Now you just look for table entries that are at most 1 apart, and the corresponding xi, xj are close enough together.

You might improve the average runtime if you check the previous and next slot when you add yi to the table. If the xi are random and linear distributed, then according to the birthday paradox you should find a close pair of numbers after about sqrt(n) operations. Asymptotic runtime won't go down, because finding minimum and maximum of xi, and clearing the table entries will take linear time already.