For instance, if I have a list
JavaScript
x
2
1
[1,4,2,3,5,4,5,6,7,8,1,3,4,5,9,10,11]
2
This algorithm should return [1,2,3,4,5,6,7,8,9,10,11].
To clarify, the longest list should run forwards. I was wondering what is an algorithmically efficient way to do this (preferably not O(n^2))?
Also, I’m open to a solution not in python since the algorithm is what matters.
Thank you.
Advertisement
Answer
Here is a simple one-pass O(n) solution:
JavaScript
1
10
10
1
s = [1,4,2,3,5,4,5,6,7,8,1,3,4,5,9,10,11,42]
2
maxrun = -1
3
rl = {}
4
for x in s:
5
run = rl[x] = rl.get(x-1, 0) + 1
6
print x-run+1, 'to', x
7
if run > maxrun:
8
maxend, maxrun = x, run
9
print range(maxend-maxrun+1, maxend+1)
10
The logic may be a little more self-evident if you think in terms of ranges instead of individual variables for the endpoint and run length:
JavaScript
1
9
1
rl = {}
2
best_range = xrange(0)
3
for x in s:
4
run = rl[x] = rl.get(x-1, 0) + 1
5
r = xrange(x-run+1, x+1)
6
if len(r) > len(best_range):
7
best_range = r
8
print list(best_range)
9