I was asked this in an interview. Given a list of integers, How can we find the biggest interval that has all its members in the given list?
E.g. given list 1,3,5,7,4,6,10 then answer would be [3, 7]. Because it has all the elements between 3 and 7.
I tried to answer but I wasn't convincing. The approach I took was to first sort the list and then check it for the biggest interval. But I was asked to do so in O(n)
.
If sorting is not desirable, you can use a combination of hash map and Disjoint-set data structure.
For each element in the list create a node and insert it into hash map with key = element's value. Then query the hash map for value+1 and value-1. If anything is found, combine current node with set(s) where adjacent nodes belong. When finished with the list, the largest set corresponds to the biggest interval.
Time complexity is O(N * α(N)) where α(N) is inverse Ackermann function.
Edit: Actually Disjoint-set is too powerful for this simple task. Solution by Grigor Gevorgyan does not use it. So it is simpler and more efficient.
I think I would have sorted them into lists of consecutive integers (assuming each number can appear only once)
take first number
if the number 1 lower than or 1 higher than a number in an existing list?
yes: pre/post pend existing list
no : create a new list starting with the current number
if there are more numbers, return to top
display the longest list
I crafted a very straightforward solution using a
HashSet
. Sincecontains
andremove
are O(1) operations, you can simply create a new interval from a random set item and 'expand' the interval it until you discover its full size, removing items from the set as you go along. The removal is key, because this is what prevents you from 'repeating' any intervals.It might help to think about it this way - the list has K intervals, whose sizes add up to N. Your task, then, is to discover what these intervals are, without repeating any intervals or items. This is why the HashSet is perfect for the job - you can efficiently remove items from the set as you expand your intervals. Then all you need to do is keep track of the largest interval as you go along.
HashSet
i = interval.start-1
i
, removei
from the set and decrement bothi
andinterval.start
interval.end
)Here is the solution in Java:
You can trade off space to get this in linear time.
The first steps are linear in your list. The last is linear in the size of A, which could be large relative to your list if you have just a few values which are far apart. But, since you're dealing with ints, A is bounded.