Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Finding closest number in a range

I thought a problem which is as follows:

We have an array A of integers of size n, and we have test cases t and in every test cases we are given a number m and a range [s,e] i.e. we are given s and e and we have to find the closest number of m in the range of that array(A[s]-A[e]).

You may assume array indexed are from 1 to n.

For example:

  A = {5, 12, 9, 18, 19}
  m = 13
  s = 4 and e = 5

So the answer should be 18.

Constraints:

n<=10^5
t<=n

All I can thought is an O(n) solution for every test case, and I think a better solution exists.

like image 670
Akashdeep Saluja Avatar asked Jan 07 '13 15:01

Akashdeep Saluja


1 Answers

This is a rough sketch: Create a segment tree from the data. At each node, besides the usual data like left and right indices, you also store the numbers found in the sub-tree rooted at that node, stored in sorted order. You can achieve this when you construct the segment tree in bottom-up order. In the node just above the leaf, you store the two leaf values in sorted order. In an intermediate node, you keep the numbers in the left child, and right child, which you can merge together using standard merging. There are O(n) nodes in the tree, and keeping this data should take overall O(nlog(n)).

Once you have this tree, for every query, walk down the path till you reach the appropriate node(s) in the given range ([s, e]). As the tutorial shows, one or more different nodes would combine to form the given range. As the tree depth is O(log(n)), that is the time per query to reach these nodes. Each query should be O(log(n)). For all the nodes which lie completely inside the range, find the closest number using binary search in the sorted array stored in those nodes. Again, O(log(n)). Find the closest among all these, and that is the answer. Thus, you can answer each query in O(log(n)) time.

The tutorial I link to contains other data structures, such as sparse table, which are easier to implement, and should give O(sqrt(n)) per query. But I haven't thought much about this.

like image 164
mayank Avatar answered Oct 21 '22 12:10

mayank