Matthis Hammel shared this problem recently:
In a street with colored houses, you want to take a picture containing the most houses, but without any duplicate colors.
In other words: find the longest possible sub-array containing only unique values.
If several options exist, you can return any of them.
Hint (only if you're stuck): https://stackoverflow.com/questions/8269916
It comes with some unit tests, and a sample, very slow O(n^2)
implementation. How can we turn it into an O(n)
implementation ?
The solution (as you can see in the heavily documented hint, well worth a read) is to use the sliding window
technique.
The core idea of this technique is to navigate the list while keeping track of two indices, start
and end
. Between those two indices, you ensure that the list always has different colors.
When the end
index moves, there is a color in its associated house:
set
of seen colors. The start
index will not move.start
index until the invariant is ensured.This is maybe easier with read python code:
def longest_unique_sublist(colors):
"""
Find the longest sublist where all the values
are different, in O(n)
"""
seen = set()
start = 0
best_start, best_end = 0, 0
# on to the sliding window
for end, color in enumerate(colors):
while color in seen:
seen.remove(colors[start])
start += 1
seen.add(color)
if end - start > best_end - best_start:
best_start, best_end = start, end
return colors[best_start:best_end+1]
That was pretty fun.