def binary_search(arr: list, e: int) -> int:
"""
适用于无重复值的有序列表, 返回目标索引
:param arr:
:param e:
:return:
"""
left = 0
right = len(arr) - 1
while left <= right:
mid = (left + right) // 2
if e == arr[mid]:
return mid
elif e < arr[mid]:
right = mid - 1
else:
left = mid + 1
return -1
def binary_search_v2(arr: list, e: int) -> int:
"""
适用于有重复值的有序列表,返回第一个匹配元素的索引
:param arr:
:param e:
:return:
"""
left = 0
right = len(arr) - 1
while left <= right:
mid = (left + right) // 2
if e == arr[mid]:
# 向前遍历,检查前面元素是否等于目标元素
'''但是这样直接遍历,时间复杂度会由O(logN) 变成 O(N)'''
while mid > 0:
mid -= 1
if e != arr[mid]:
# 直到检查元素不等于目标元素为止,目标索引加1,即后一个匹配的元素的索引,然后跳出
mid += 1
break
return mid
elif e < arr[mid]:
right = mid - 1
else:
left = mid + 1
return -1
def binary_search_v3(arr: list, e: int) -> int:
"""
适用于有重复值的有序列表,返回第一个匹配元素的索引, 即找出元素索引下限
时间复杂度:O(logN)
比v2的写法平均快4倍
:param arr:
:param e:
:return:
"""
left = 0
right = len(arr) - 1
while left < right:
mid = (left + right) // 2
if e <= arr[mid]:
# 求下限, 即从右向左逼近
right = mid
else:
left = mid + 1
if arr[left] != e:
return -1
return left
def binary_search_v4(arr: list, e: int) -> int:
"""
有序列表, 找出元素索引上限
:param arr:
:param e:
:return:
"""
left = 0
right = len(arr) - 1
while left < right:
mid = (left + right) // 2 + 1 # 不加一,在某些情况下会死循环
if e >= arr[mid]:
# 求上限, 即从左向右逼近
left = mid
else:
right = mid - 1
if arr[left] != e:
return -1
return left
def binary_search_v5(arr: list, e: int) -> list:
"""
有序可重复值的列表中,找出目标元素上下限索引
:param arr:
:param e:
:return:
"""
# 找下限
result = []
left = 0
RIGHT = len(arr) - 1
right = RIGHT
while left < right:
mid = (left + right) // 2
if e <= arr[mid]:
right = mid
else:
left = mid + 1
if e != arr[left]:
return [-1, -1]
result.append(left)
if left == RIGHT:
return [left, left]
# 找上限
right = RIGHT
# left是下限, 在left到RGHT范围中找
while left < right:
mid = (left + right) // 2 + 1
if e >= arr[mid]:
left = mid
else:
right = mid - 1
result.append(right)
return result
二分法查找-python实现-无重复值与有重复值的情况
最新推荐文章于 2022-11-26 10:40:43 发布