学習したことのアウトプットとして
バイナリーサーチを用いた問題、理屈はわかるが、実際自分でコードを描こうとすると脳が混乱…。
ので、自分なりに整理してみようかと。
##”バイナリーサーチ”とは
ソート済みのリストや配列に入ったデータ(同一の値はないものとする)に対する検索を行うときに用いられる手法。
中央の値を確認し、検索したい値との大小関係を用いて、検索したい値が中央の値の右にあるか、左にあるかを判断。
それを繰り返し、片側には存在しないことを確かめながら検索していく方法。
例)ある配列にある13の位置を知りたい
2 | 3 | 5 | 6 | 8 |
10 | 11 | 13 | 16 |
---|---|---|---|---|---|---|---|---|
4番目の"8"が要素の中央。13は8より大きいので、次は"10"を左端として検索
|
||||||||
↓ |
10 | 11 |
13 | 16 |
---|---|---|---|
6番目の"11"が要素の中央。13は11より大きので、次は"13"を左端として検索
|
|||
↓ |
13 |
16 |
---|---|
7番目の"13"が要素の中央。検索したい13と合致 | |
↓ | |
「13は配列の7番目」 |
という風な感じ。理屈自体は難しいものではないかと。
要素数が偶数の場合、「中央」は数が少ない方(左側)が優先されるのか?
詳しい人がいらっしゃればコメントいただけると幸いです。
###問題
以下の配列に任意の値が存在するかどうか、そして何番目に存在するのか、検索するコードを作成しましょう。
添字が0の要素、つまり以下の配列における「1」は「配列の0番目に存在する」と表現します。
array=[1,3,5,6,9,10,13,20,26,31]
任意の値が配列内に存在しない場合は、「値は配列内に存在しません」と表示し、
存在する場合は、配列の何番目にあるかを表示してください。
※配列の上限である32以上の値による検索は想定しないものとする。
###模範解答
def binary_search(array, right, target)
left = 0
while left <= right
center = (left + right) / 2
if array[center] == target
return center
elsif array[center] < target
left = center + 1
else
right = center - 1
end
end
return -1
end
array=[1,3,5,6,9,10,13,20,26,31]
puts "検索したい数字を入力してください"
target = gets.to_i
number_of_elements = array.length
result = binary_search(array, number_of_elements, target)
if result == -1
puts "#{target}は配列内に存在しません"
else
puts "#{target}は配列の#{result}番目に存在します "
end
###解説
1〜14行目
def binary_search(array, right, target)
left = 0
while left <= right
center = (left + right) / 2
if array[center] == target
return center
elsif array[center] < target
left = center + 1
else
right = center - 1
end
end
return -1
end
たとえば、targetとして"20"を入力した場合を考えてみる
1回目のループ
def binary_search(array, right, target) #(配列,10(配列の数),20)
left = 0
while left <= right #0 <= 10 はtureで処理が実行される
center = (left + right) / 2 #要素の中央 (0+10) / 2 = 5
if array[center] == target #array[5]は"10"でfalseなので、この処理はされない
return center
elsif array[center] < target #trueなのでこの処理が実行される
left = center + 1 #2回目のループではleft=6(配列の中央から右側に検索範囲を絞る)
else
right = center - 1
end
end
return -1
end
2回目のループ
def binary_search(array, right, target) #(配列,10(配列の数),20)
left = 6 #1回目のループより
while left <= right #6 <= 10 はtureで処理が実行される
center = (left + right) / 2 #要素の中央 (6+10) / 2 = 8
if array[center] == target #array[8]は"26"でfalseなので、この処理はされない
return center
elsif array[center] < target #26 < 20 でfalse
left = center + 1
else
right = center - 1 #ここの処理がされる。3回目のループではright=9(1回目で絞った配列からさらに中央から左側に検索範囲を絞る)
end
end
return -1
end
3回目のループ
def binary_search(array, right, target) #(配列,10(配列の数),20)
left = 6 #1回目のループより
while left <= right #6 <= 9(2回目のループより) はtureで処理が実行される
center = (left + right) / 2 #要素の中央 (6+9) / 2 = 7
if array[center] == target #array[7]は"20"でture
return center #7 が返り値となる
elsif array[center] < target
left = center + 1
else
right = center - 1
end
end
return -1
end
13行目のreturn -1
は何も当てはまるときがないときに、最終的な返り値になる。
返り値を元に条件分岐を利用して出力内容を設定する。
記事を書いて、少し自分の中でも整理できたのでよかった!