def missPos(a):
b={x for x in a}
for x in range(1,len(b)+2):
if not x in b:
return x def missPos(a):
b={x for x in a}
for x in range(1,len(b)+2):
if not x in b:
return x def miss_pos(a):
b = range(1, len(a)+2)
return min(set(b).difference(a))
It's probably not as efficient, but remember the first rule of optimization: http://c2.com/cgi/wiki?FirstRuleOfOptimizationI do like your solution better though, but mostly because it doesn't mutate the array passed to the function. A function called "firstMissingPositive" shouldn't modify state.
Actual times definitely more than O(N) growth.
a10k = []
for x in range(10000):
a10k.append(randint(1,20000))
%timeit b10k = set(a10k)
10k elements = 364 microseconds/loop
100k elements = 5 milliseconds/loop
1mm elements = 170 milliseconds/loop
10mm elements = 2.4 seconds/loop.
100mm elements = 34.5 seconds/loop
Presumably the jump from 100k elements to 1mm elements hit that "cache locality" boundary you were referring to.Edit - nevermind. It's a hash table of course. So I'm wrong.
Also, the average case for set membership testing is O(1), so the average case runtime would actually be O(N).
Back then when I was still looking for job, I was asked this question by a startup. I gave out this hashset solution and was quickly asked if O(1) space solution was available and then asked to implemented it.
If the space restriction is not an issue, I would definitely go with the method you suggested. Way more succinct and easier to follow.
Is there an advantage in using a set comprehension over set(a) or is it just a stylistic choice?
The set function is somewhat faster.
a=[]
for x in range(10000):
a.append(randint(1,2000))
%timeit b=set(a)
1000 loops, best of 3: 373 µs per loop
%timeit b={x for x in a}
1000 loops, best of 3: 542 µs per loop