pythonでバイナリ検索を実装しようとしていますが、次のように記述しました。ただし、needle_elementが配列内の最大要素より大きい場合は停止できません。
手伝ってくれますか?ありがとう。
def binary_search(array, needle_element):
mid = (len(array)) / 2
if not len(array):
raise "Error"
if needle_element == array[mid]:
return mid
Elif needle_element > array[mid]:
return mid + binary_search(array[mid:],needle_element)
Elif needle_element < array[mid]:
return binary_search(array[:mid],needle_element)
else:
raise "Error"
needle_element > array[mid]
、あなたは現在array[mid:]
再帰呼び出しに。ただし、array[mid]
は小さすぎるため、array[mid+1:]
代わりに(それに応じて返されるインデックスを調整します)。
針が配列内のすべての要素よりも大きい場合、この方法でやると最終的に空の配列が得られ、期待どおりにエラーが発生します。
注:毎回サブアレイを作成すると、大きなアレイのパフォーマンスが低下します。代わりに、配列の境界を渡すことをお勧めします。
Lasse V. Karlsenが質問へのコメントで示唆しているように、lower
およびupper
インデックスを使用する方がはるかに良いでしょう。
これはコードになります:
def binary_search(array, target):
lower = 0
upper = len(array)
while lower < upper: # use < instead of <=
x = lower + (upper - lower) // 2
val = array[x]
if target == val:
return x
Elif target > val:
if lower == x: # these two are the actual lines
break # you're looking for
lower = x
Elif target < val:
upper = x
lower < upper
(左側から)小さい数に達すると停止しますif lower == x: break
は、(右側から)より高い数値に達すると停止します例:
>>> binary_search([1,5,8,10], 5) # return 1
1
>>> binary_search([1,5,8,10], 0) # return None
>>> binary_search([1,5,8,10], 15) # return None
なぜbisectモジュールを使用しないのですか?それはあなたが必要とする仕事をするべきです---あなたが維持し、テストするためのより少ないコード。
array [mid:]は、slow = slowと呼ばれるたびに新しいサブコピーを作成します。また、再帰を使用します。Pythonも遅いです。
これを試して:
def binarysearch(sequence, value):
lo, hi = 0, len(sequence) - 1
while lo <= hi:
mid = (lo + hi) // 2
if sequence[mid] < value:
lo = mid + 1
Elif value < sequence[mid]:
hi = mid - 1
else:
return mid
return None
他の人が提案したようにアルゴリズムを改善できますが、まずそれがなぜ機能しないのか見てみましょう:
_needle_element > array[mid]
_の場合、次に検索する二分された配列に要素mid
が含まれているため、ループに陥ります。したがって、針が配列にない場合、最終的に長さ1の配列を永久に検索することになります。代わりに_array[mid+1:]
_を渡し(_mid+1
_が有効なインデックスでない場合でも有効です)、最終的に長さゼロの配列で関数を呼び出します。したがって、len(array) == 0
は、エラーではなく「見つかりません」という意味です。適切に処理してください。
def binary_search(array, target):
low = 0
mid = len(array) / 2
upper = len(array)
if len(array) == 1:
if array[0] == target:
print target
return array[0]
else:
return False
if target == array[mid]:
print array[mid]
return mid
else:
if mid > low:
arrayl = array[0:mid]
binary_search(arrayl, target)
if upper > mid:
arrayu = array[mid:len(array)]
binary_search(arrayu, target)
if __name__ == "__main__":
a = [3,2,9,8,4,1,9,6,5,9,7]
binary_search(a,9)
これは末尾再帰ソリューションです。これは、部分配列をコピーしてから、返されるインデックスを追跡するよりもきれいだと思います。
def binarySearch(elem, arr):
# return the index at which elem lies, or return false
# if elem is not found
# pre: array must be sorted
return binarySearchHelper(elem, arr, 0, len(arr) - 1)
def binarySearchHelper(elem, arr, start, end):
if start > end:
return False
mid = (start + end)//2
if arr[mid] == elem:
return mid
Elif arr[mid] > elem:
# recurse to the left of mid
return binarySearchHelper(elem, arr, start, mid - 1)
else:
# recurse to the right of mid
return binarySearchHelper(elem, arr, mid + 1, end)
上記の答えはすべて真実ですが、コードを共有すると役立つと思います
def binary_search(number):
numbers_list = range(20, 100)
i = 0
j = len(numbers_list)
while i < j:
middle = int((i + j) / 2)
if number > numbers_list[middle]:
i = middle + 1
else:
j = middle
return 'the index is '+str(i)
再帰を使用する:
def binarySearch(arr,item):
c = len(arr)//2
if item > arr[c]:
ans = binarySearch(arr[c+1:],item)
if ans:
return binarySearch(arr[c+1],item)+c+1
Elif item < arr[c]:
return binarySearch(arr[:c],item)
else:
return c
binarySearch([1,5,8,10,20,50,60],10)
下位/上位インデックスがなければ、これも行う必要があります。
def exists_element(element, array):
if not array:
yield False
mid = len(array) // 2
if element == array[mid]:
yield True
Elif element < array[mid]:
yield from exists_element(element, array[:mid])
else:
yield from exists_element(element, array[mid + 1:])
再帰を使用して配列のキーのインデックスを返します。
round()は、floatを整数に変換し、コードを高速化する関数であり、期待されるcase [O(logn)]に進みます。
A=[1,2,3,4,5,6,7,8,9,10]
low = 0
hi = len(A)
v=3
def BS(A,low,hi,v):
mid = round((hi+low)/2.0)
if v == mid:
print ("You have found dude!" + " " + "Index of v is ", A.index(v))
Elif v < mid:
print ("Item is smaller than mid")
hi = mid-1
BS(A,low,hi,v)
else :
print ("Item is greater than mid")
low = mid + 1
BS(A,low,hi,v)
BS(A,low,hi,v)
バイナリ検索を実行している場合、配列がソートされていると推測しています。それが当てはまる場合、配列の最後の要素をneedle_element
と比較できるはずです。タコが言うように、これは検索が始まる前に行うことができます。
needle_element
は、開始する前に配列の境界内にあります。これにより、最後まで到達するためにいくつかの手順を実行する必要がないため、より効率的になります。
if needle_element < array[0] or needle_element > array[-1]:
# do something, raise error perhaps?
値がリストにある場合、ブール値を返します。
リストの最初と最後のインデックスをキャプチャし、中間値をキャプチャしてリストをループおよび分割します。各ループで同じことを行い、値の入力が中間値に等しいかどうかを比較します。
def binarySearch(array, value):
array = sorted(array)
first = 0
last = len(array) - 1
while first <= last:
midIndex = (first + last) // 2
midValue = array[midIndex]
if value == midValue:
return True
if value < midValue:
last = midIndex - 1
if value > midValue:
first = midIndex + 1
return False