計算量・考え方はmex2と同じですが、オマケでnumpyを使ったmex5を作ってみました。
速度はmex2より2割くらいマシですが、mex1, 3, 4より遅いですね。
ディスカッションのスタート用に何パタンか書いてみました。
ソートして二分探索するとワースト実行時間を改善できるかと思いましたが、
おそらくmex3
にはバグがある
探す値がリストの前半にある場合、シンプルな実装より遅い
ので、自分で書くならmex4
ですかね。
python
1
2 from timeit import timeit
3 from random import choices , shuffle
4 import numpy as np
5
6 def mex1 ( inp ) :
7 check = set ( inp ) # set化しないと遅い
8 ans = 1
9 while ans in check :
10 ans += 1
11 return ans
12
13 def mex2 ( inp ) :
14 N = max ( inp )
15 judge = [ 0 ] * ( N + 2 )
16 ans = 1
17 for i in inp :
18 judge [ i ] = 1
19 while judge [ ans ] == 1 :
20 ans += 1
21 return ans
22
23 # 二分探索っぽく探す(未チェック)
24 def mex3 ( inp ) :
25 arr = sorted ( set ( inp ) )
26 lb , ub = - 1 , len ( arr )
27 while ub > lb + 1 :
28 mid = ( lb + ub ) // 2
29 lb , ub = ( mid , ub ) if arr [ mid ] == mid + 1 else ( lb , mid )
30 return arr [ lb ] + 1 if lb != - 1 else 1
31
32 # mex1を書換えただけ
33 def mex4 ( inp ) :
34 check = set ( inp )
35 return next ( i for i in range ( 1 , len ( check ) + 2 ) if i not in check )
36
37 # mex2と同じ考え方をnumpyブール型で
38 def mex5 ( inp ) :
39 arr = np . array ( inp )
40 sieve = np . zeros ( len ( inp ) + 10 , dtype = bool )
41 sieve [ 0 ] = True
42 sieve [ np . where ( arr > len ( inp ) , 0 , arr ) ] = True
43 return np . where ( sieve == False ) [ 0 ] [ 0 ]
44
45 size = 10 ** 6
46 ans = { 987654 , 525252 } # この数字以外のリストを生成
47 arr = [ i for i in range ( 1 , size ) if i not in ans ]
48 arr = arr + list ( choices ( arr * 5 , k = size * 3 ) ) # 重複を入れていろいろまぜる
49 shuffle ( arr )
50
51 r1 = mex1 ( arr )
52 r2 = mex2 ( arr )
53 r3 = mex3 ( arr )
54 r4 = mex4 ( arr )
55 print ( r1 == r2 == r3 == r4 , r1 , min ( ans ) ) # 同じ答えになっているかチェック
56
57 print ( 'mex1' , timeit ( 'mex1(arr)' , globals = globals ( ) , number = 5 ) )
58 print ( 'mex2' , timeit ( 'mex2(arr)' , globals = globals ( ) , number = 5 ) )
59 print ( 'mex3' , timeit ( 'mex3(arr)' , globals = globals ( ) , number = 5 ) )
60 print ( 'mex4' , timeit ( 'mex4(arr)' , globals = globals ( ) , number = 5 ) )
61
62 # mex1 2.0568706
63 # mex2 6.3567640999999995
64 # mex3 1.801850899999998
65 # mex4 2.099546499999999