Processing math: 100%

[Python] 2分探索

2分探索

二分探索(にぶんたんさく、: binary search、BS)やバイナリサーチとは、ソート済み配列に対する探索アルゴリズムの一つ。

出典: フリー百科事典『ウィキペディア(Wikipedia)』

ソート済みのリストにおいて、 目標との中央の値の大小関係により、目標が中央の値の右にあるか、左にあるかを判断することで、目標のある場所を絞り込んでいく検索アルゴリズムです。

時間計算量は O(logn) 、空間計算量は O(1) になります。

import random
def binary_search(lst, target_val):
low = 0
high = len(lst) - 1
while low <= high:
mid = (low + high) // 2
if lst[mid] > target_val:
high = mid - 1
elif lst[mid] < target_val:
low = mid + 1
else:
return mid
return False
def print_serach_result(lst, target_val):
target_index = binary_search(lst, target_val)
if target_index:
print(f'{target_val}は{target_index+1}番目に見つかりました。')
else:
print(f'{target_val}はリストの中にありません。')
if __name__ == '__main__':
# 適当なリストの生成
random.seed(1)
lst = [random.randint(1, 100) for _ in range(10)]
lst.sort()
# [9, 16, 18, 33, 58, 61, 64, 73, 98, 98]
print(lst)
# 線形探索
# 64は7番目に見つかりました。
print_serach_result(lst, 64)
# 63はリストの中にありません。
print_serach_result(lst, 63)
import random def binary_search(lst, target_val): low = 0 high = len(lst) - 1 while low <= high: mid = (low + high) // 2 if lst[mid] > target_val: high = mid - 1 elif lst[mid] < target_val: low = mid + 1 else: return mid return False def print_serach_result(lst, target_val): target_index = binary_search(lst, target_val) if target_index: print(f'{target_val}は{target_index+1}番目に見つかりました。') else: print(f'{target_val}はリストの中にありません。') if __name__ == '__main__': # 適当なリストの生成 random.seed(1) lst = [random.randint(1, 100) for _ in range(10)] lst.sort() # [9, 16, 18, 33, 58, 61, 64, 73, 98, 98] print(lst) # 線形探索 # 64は7番目に見つかりました。 print_serach_result(lst, 64) # 63はリストの中にありません。 print_serach_result(lst, 63)
 import random

def binary_search(lst, target_val):
    low = 0
    high = len(lst) - 1
    while low <= high:
        mid = (low + high) // 2
        if lst[mid] > target_val:
            high = mid - 1
        elif lst[mid] < target_val:
            low = mid + 1
        else:
            return mid
    return False

def print_serach_result(lst, target_val):
    target_index = binary_search(lst, target_val)
    if target_index:
        print(f'{target_val}は{target_index+1}番目に見つかりました。')
    else:
        print(f'{target_val}はリストの中にありません。')


if __name__ == '__main__':
    # 適当なリストの生成
    random.seed(1)
    lst = [random.randint(1, 100) for _ in range(10)]
    lst.sort()
    # [9, 16, 18, 33, 58, 61, 64, 73, 98, 98]
    print(lst) 

    # 線形探索
    # 64は7番目に見つかりました。
    print_serach_result(lst, 64)
    # 63はリストの中にありません。
    print_serach_result(lst, 63)

想定通りの結果を得ることができました。

また、再帰を用いてコードを記述してみます。

import random
def binary_search_recursive(lst, target_val, low=0, high=-1):
if not lst:
return False
if high == -1:
high = len(lst) -1
if low == high:
if lst[low] == target_val:
return low
else:
return False
mid = low + (high -low) // 2
if lst[mid] > target_val:
return binary_search_recursive(lst, target_val, low, mid-1)
elif lst[mid] < target_val:
return binary_search_recursive(lst, target_val, mid+1, high)
else:
return mid
def print_serach_result(lst, target_val):
target_index = binary_search_recursive(lst, target_val)
if target_index:
print(f'{target_val}は{target_index+1}番目に見つかりました。')
else:
print(f'{target_val}はリストの中にありません。')
if __name__ == '__main__':
# 適当なリストの生成
random.seed(1)
lst = [random.randint(1, 100) for _ in range(10)]
lst.sort()
# [9, 16, 18, 33, 58, 61, 64, 73, 98, 98]
print(lst)
# 線形探索
# 64は7番目に見つかりました。
print_serach_result(lst, 64)
# 63はリストの中にありません。
print_serach_result(lst, 63)
import random def binary_search_recursive(lst, target_val, low=0, high=-1): if not lst: return False if high == -1: high = len(lst) -1 if low == high: if lst[low] == target_val: return low else: return False mid = low + (high -low) // 2 if lst[mid] > target_val: return binary_search_recursive(lst, target_val, low, mid-1) elif lst[mid] < target_val: return binary_search_recursive(lst, target_val, mid+1, high) else: return mid def print_serach_result(lst, target_val): target_index = binary_search_recursive(lst, target_val) if target_index: print(f'{target_val}は{target_index+1}番目に見つかりました。') else: print(f'{target_val}はリストの中にありません。') if __name__ == '__main__': # 適当なリストの生成 random.seed(1) lst = [random.randint(1, 100) for _ in range(10)] lst.sort() # [9, 16, 18, 33, 58, 61, 64, 73, 98, 98] print(lst) # 線形探索 # 64は7番目に見つかりました。 print_serach_result(lst, 64) # 63はリストの中にありません。 print_serach_result(lst, 63)
import random

def binary_search_recursive(lst, target_val, low=0, high=-1):
    if not lst:
        return False
    if high == -1:
        high = len(lst) -1
    if low == high:
        if lst[low] == target_val:
            return low
        else:
            return False
    mid = low + (high -low) // 2
    if lst[mid] > target_val:
        return binary_search_recursive(lst, target_val, low, mid-1)
    elif lst[mid] < target_val:
        return binary_search_recursive(lst, target_val, mid+1, high)
    else:
        return mid

def print_serach_result(lst, target_val):
    target_index = binary_search_recursive(lst, target_val)
    if target_index:
        print(f'{target_val}は{target_index+1}番目に見つかりました。')
    else:
        print(f'{target_val}はリストの中にありません。')


if __name__ == '__main__':
    # 適当なリストの生成
    random.seed(1)
    lst = [random.randint(1, 100) for _ in range(10)]
    lst.sort()
    # [9, 16, 18, 33, 58, 61, 64, 73, 98, 98]
    print(lst) 

    # 線形探索
    # 64は7番目に見つかりました。
    print_serach_result(lst, 64)
    # 63はリストの中にありません。
    print_serach_result(lst, 63)

こちらも想定通りの結果を得ることができました。