# Search in a sorted matrix with an oracle

Consider a infinite matrix $M$. Another way to think about it is a function $f:N→N→X$. A matrix $M$ is sorted if $M_{i,j}≤M_{i,j+1}$ and $M_{i,j}≤M_{i+1,j}$.

Given a sorted matrix $M$, and an oracle that takes $λ$ returns if a value is $λ<λ_{∗}$ or $λ≥λ_{∗}$. Find the largest value no larger than $λ_{∗}$.

Assuming there are at most $k$ elements no larger than $λ_{∗}$, and we know the smallest $n$ and $m$ such that $M_{i,j}>λ_{∗}$ if $i>n$ or $j>m$. Also, let $t$ be the smallest number such that $M_{t,t}>λ_{∗}$. One can see that $t≤min(n,m)$ and $k=O(max(n,m)_{2})$.

Let’s first consider the case when $n$ and $m$ is known and $n≤m$. It is Leetcode 240. Search a 2D Matrix II. However, our problem is more general, because comparison with $λ_{∗}$ can only be done through the oracle. Craig Gidney wrote about an optimal algorithm with $O(ngnm )$ running time, matrix access algorithm. However, the oracle access is too large. There are times where the oracle access is slow. For example, when using it as a subroutine for finding a bottleneck $k$-link path. There is an algorithm with optimal running time and $O(g(nm))$ oracle access.

Let’s consider a special case, where $n=m=2_{i}$ for some $i$. This case was shown in [1]. For each submatrix, the two vertices on the opposite diagonal indicates the largest and smallest element in the submatrix. Hence each matrix can be represented by two numbers, indicate the maximum and minimum. These numbers are called the representative of the matrix. The idea is we keep two numbers $λ_{1}$ and $λ_{2}$, such that we know $λ_{∗}∈[λ_{1},λ_{2}]$. The algorithm keep partition the matrix into small matrices, updating $λ_{1}$ and $λ_{2}$, and discard matrices outside the range. We apply the following algorithm. Let $R$ consists of the multiset of representatives of the matrix, and $R_{′}$ be the representatives that lies inside $[λ_{1},λ_{2}]$. We find $λ$, the median of $R_{′}$. Test if $λ<λ_{∗}$. If so, then $λ_{1}$ updates to $λ$, otherwise $λ_{2}$ updates to $λ$. This step is done twice. Now, we split the matrices with more than one element into $4$ equally sized matrices, and repeat the algorithm. Recall at all times, the matrices does not contain any element in $[λ_{1},λ_{2}]$ are discarded.

There is at most $O(gn)$ iterations before range shrinks to a single element, hence at most $O(gn)$ oracle calls. The difficulty is to show that the overall time is only $O(n)$. Intuitively, in each iteration we quadruple the number of matrices, but we half it by two calls to the oracle. Therefore in $gn$ steps we obtain roughly $2_{logn}=O(n)$ matrices. However, at this point, the matrices are all singletons, and no more matrix can be created. We will only decrease the number of matrices by each oracle call. Careful reader can trace the whole argument in Lemma 2.1 of [1].

For the more general case, one can find the proof in [2]. Note the proof is for selection, but one can easily modify it to work for search.

Now, $n$ and $m$ is not known, but we can quickly using exponential search to find it. Indeed, we just have to apply exponential search in the first row and first column using the oracle. This gives us an extra $O(gn+gm)=O(gnm)$ oracle calls.

Let $k$ to be the number of elements no larger than $λ_{∗}$. We can get running time relative to $k$. Use exponential search until we find the first $i$ such that $M_{2_{i},2_{i}}>λ_{∗}$. So we can upper bound $t$. Then one can solve the problem with $2$ matrices. One $t×k$ matrix and a $k×t$ matrix. The total running time is therefore $O(gk+tgk/t)=O(tgk)$. In fact, we get $O(gk)$ oracle calls and $O(tgk)$ running time. Here we can take $t$ to be $k $, and obtain $O(k gk)$ time.

Note if we relax on number of oracle calls. I know how to get a $O(k )$ running time.

Given $λ_{∗}$ and a $n×m$ sorted matrix such that the $i$th row has $k_{i}$ elements no larger than $x$. Let $k=∑_{i}k_{i}$. We can find $λ_{∗}$ in $O(∑_{i}g(k_{i+1}−k_{i}+1))=O(ngn_{2}k )$ time.

The idea is simple, we do exponential search on each row to find the largest element no larger than $λ_{∗}$, but we reuse information from the previous row. This gives us the running time $O(∑_{i}g(k_{i+1}−k_{i}+1))$. The main difficulty is to show why is is $O(ngn_{2}k )$.

If $∑_{i=1}k_{i}=k$, then $∑_{i=1}g(k_{i+1}−k_{i}+1)=O(ngk/n_{2})=O(ngk/n)$.

Once we show that, we can use the theorem to obtain $O(k )$ running time.

In fact, we can also get a very simple algorithm with running time $O(hg(k/h))$, where $h$ is the number of stairs in the staircase shape. However, it also uses $O(hg(k/h)$ oracle calls. The idea is to use exponential search to find the boundary of the staircase, but we switch between boundaries: horizontal then vertical.

What about the best of both worlds? That is, $O(hg(k/h))$ running time and $O(gk)$ oracle calls.

There is an alternative algorithm which can be found in [3]. The alternative algorithm is quite
close to a post about selection
in a sorted matrix. The careful reader might observe the known
search algorithms follow the exact same structure as algorithms for
selection. Indeed, we *are* doing selection but we do not know
the rank of the element. Intuitively, many selection algorithm, the rank
is *only used* to remove the correct set of candidates. Hence
this suggest one can modify the algorithm to use the oracle call in
place of the rank.

The paper [3] actually also have an optimum algorithm.

Given a $n×m$ sorted matrix where $n≤m$ and there are $h$ stairs, and an oracle that decide if a value is greater, lesser of equal to $λ_{∗}$. We can find $λ_{∗}$ in $O(pgpm )$ time and matrix access, and $O(g(nm))$ oracle calls.

# References

**Optimal parametric search for path and tree partitioning**, CoRR. abs/1711.00599 (2017).

**Generalized selection and ranking: Sorted matrices**, SIAM Journal on Computing. 13 (1984) 14–30 10.1137/0213002.

**Binary search on two-dimensional data**, Technische Universität München, 2008.