配列でのバイナリ検索の基本的な考え方は単純ですが、検索で正確なアイテムが見つからない場合は、「近似」インデックスが返される可能性があります。(値が検索された値よりも大きいまたは小さいインデックスが返される場合があります)。
正確な挿入ポイントを探すために、おおよその位置を取得した後、正確な挿入位置を左または右に「スキャン」する必要があるようです。たとえば、Rubyでは次のことができます。arr.insert(exact_index, value)
私は次の解決策を持っていますが、パーツの取り扱いがbegin_index >= end_index
少し面倒です。よりエレガントなソリューションを使用できるかどうか疑問に思いますか?
(このソリューションは、完全一致が見つかった場合に複数の一致をスキャンする必要がないため、完全一致に対して返されるインデックスは、値に対応する任意のインデックスを指している可能性があります...しかし、それらがすべて整数である場合、a - 1
完全に一致するものが見つかった後、左側の境界を検索するか、右側の境界を検索するために、いつでも検索できますa + 1
。)
私の解決策:
DEBUGGING = true
def binary_search_helper(arr, a, begin_index, end_index)
middle_index = (begin_index + end_index) / 2
puts "a = #{a}, arr[middle_index] = #{arr[middle_index]}, " +
"begin_index = #{begin_index}, end_index = #{end_index}, " +
"middle_index = #{middle_index}" if DEBUGGING
if arr[middle_index] == a
return middle_index
elsif begin_index >= end_index
index = [begin_index, end_index].min
return index if a < arr[index] && index >= 0 #careful because -1 means end of array
index = [begin_index, end_index].max
return index if a < arr[index] && index >= 0
return index + 1
elsif a > arr[middle_index]
return binary_search_helper(arr, a, middle_index + 1, end_index)
else
return binary_search_helper(arr, a, begin_index, middle_index - 1)
end
end
# for [1,3,5,7,9], searching for 6 will return index for 7 for insertion
# if exact match is found, then return that index
def binary_search(arr, a)
puts "\nSearching for #{a} in #{arr}" if DEBUGGING
return 0 if arr.empty?
result = binary_search_helper(arr, a, 0, arr.length - 1)
puts "the result is #{result}, the index for value #{arr[result].inspect}" if DEBUGGING
return result
end
arr = [1,3,5,7,9]
b = 6
arr.insert(binary_search(arr, b), b)
p arr
arr = [1,3,5,7,9,11]
b = 6
arr.insert(binary_search(arr, b), b)
p arr
arr = [1,3,5,7,9]
b = 60
arr.insert(binary_search(arr, b), b)
p arr
arr = [1,3,5,7,9,11]
b = 60
arr.insert(binary_search(arr, b), b)
p arr
arr = [1,3,5,7,9]
b = -60
arr.insert(binary_search(arr, b), b)
p arr
arr = [1,3,5,7,9,11]
b = -60
arr.insert(binary_search(arr, b), b)
p arr
arr = [1]
b = -60
arr.insert(binary_search(arr, b), b)
p arr
arr = [1]
b = 60
arr.insert(binary_search(arr, b), b)
p arr
arr = []
b = 60
arr.insert(binary_search(arr, b), b)
p arr
結果:
Searching for 6 in [1, 3, 5, 7, 9]
a = 6, arr[middle_index] = 5, begin_index = 0, end_index = 4, middle_index = 2
a = 6, arr[middle_index] = 7, begin_index = 3, end_index = 4, middle_index = 3
a = 6, arr[middle_index] = 5, begin_index = 3, end_index = 2, middle_index = 2
the result is 3, the index for value 7
[1, 3, 5, 6, 7, 9]
Searching for 6 in [1, 3, 5, 7, 9, 11]
a = 6, arr[middle_index] = 5, begin_index = 0, end_index = 5, middle_index = 2
a = 6, arr[middle_index] = 9, begin_index = 3, end_index = 5, middle_index = 4
a = 6, arr[middle_index] = 7, begin_index = 3, end_index = 3, middle_index = 3
the result is 3, the index for value 7
[1, 3, 5, 6, 7, 9, 11]
Searching for 60 in [1, 3, 5, 7, 9]
a = 60, arr[middle_index] = 5, begin_index = 0, end_index = 4, middle_index = 2
a = 60, arr[middle_index] = 7, begin_index = 3, end_index = 4, middle_index = 3
a = 60, arr[middle_index] = 9, begin_index = 4, end_index = 4, middle_index = 4
the result is 5, the index for value nil
[1, 3, 5, 7, 9, 60]
Searching for 60 in [1, 3, 5, 7, 9, 11]
a = 60, arr[middle_index] = 5, begin_index = 0, end_index = 5, middle_index = 2
a = 60, arr[middle_index] = 9, begin_index = 3, end_index = 5, middle_index = 4
a = 60, arr[middle_index] = 11, begin_index = 5, end_index = 5, middle_index = 5
the result is 6, the index for value nil
[1, 3, 5, 7, 9, 11, 60]
Searching for -60 in [1, 3, 5, 7, 9]
a = -60, arr[middle_index] = 5, begin_index = 0, end_index = 4, middle_index = 2
a = -60, arr[middle_index] = 1, begin_index = 0, end_index = 1, middle_index = 0
a = -60, arr[middle_index] = 9, begin_index = 0, end_index = -1, middle_index = -1
the result is 0, the index for value 1
[-60, 1, 3, 5, 7, 9]
Searching for -60 in [1, 3, 5, 7, 9, 11]
a = -60, arr[middle_index] = 5, begin_index = 0, end_index = 5, middle_index = 2
a = -60, arr[middle_index] = 1, begin_index = 0, end_index = 1, middle_index = 0
a = -60, arr[middle_index] = 11, begin_index = 0, end_index = -1, middle_index = -1
the result is 0, the index for value 1
[-60, 1, 3, 5, 7, 9, 11]
Searching for -60 in [1]
a = -60, arr[middle_index] = 1, begin_index = 0, end_index = 0, middle_index = 0
the result is 0, the index for value 1
[-60, 1]
Searching for 60 in [1]
a = 60, arr[middle_index] = 1, begin_index = 0, end_index = 0, middle_index = 0
the result is 1, the index for value nil
[1, 60]
Searching for 60 in []
[60]