赞
踩
下面是二分查找的最基本形式, 其原理是通过判断中间元素与目标值的大小来确定搜索方向的, 这种方法不需要后处理, 因为该方法在搜索目标元素的时候会不断向两侧偏移, 倘若找不到目标元素, 索引会偏移到数组末尾.
left = 0, right = length-1
left > right
right = mid-1
left = mid+1
def binarySearch(arr: List[int], target: int) -> int:
lo,hi = 0,len(arr)-1
while lo <= hi:
mid = (lo + hi) // 2
if arr[mid] > target:
lo = mid + 1
elif arr[mid] < target:
hi = mid - 1
else:
return mid
return -1 # 这种方法能够遍历所有元素, 当越界则说明找不到
查找左右边界的模板适用于存在多个符合条件的数, 并要求找到索引最大/最小的情况. 对于出现重复的情况, 需要将边界值设置为中间值, 以不断逼近目标.
注意, 在查找右边界过程中, 是通过mid
不断向右偏移来查找右端点的, 因此需要取
m
i
d
=
1
+
⌊
l
e
f
t
+
r
i
g
h
t
2
⌋
mid=1 + \lfloor \frac{left+right}{2}\rfloor
mid=1+⌊2left+right⌋; 而在查找左端点的场景中, 是通过mid
不断向左偏移来查找左端点的, 因此需要取
m
i
d
=
⌊
l
e
f
t
+
r
i
g
h
t
2
⌋
mid=\lfloor \frac{left+right}{2}\rfloor
mid=⌊2left+right⌋
left = 0, right = length-1
mid = (left + right) / 2
left == right
right = mid
left = mid+1
left = 0, right = length-1
mid = 1 + (left + right) / 2
left == right
right = mid - 1
left = mid
def leftBinarySearch(arr: List[int], target: int) -> int: if not arr: return -1 lo, hi = 0, len(arr)-1 while lo < hi: mid = (lo+hi)//2 if arr[mid] < target: lo = mid + 1 else: hi = mid return hi if arr[hi] == target else -1 def rightBinarySearch(arr: List[int], target: int) -> int: if not arr: return -1 lo, hi = 0, len(arr)-1 while lo < hi: mid = (lo + hi) // 2 + 1 if arr[mid] > target: hi = mid - 1 else: lo = mid return lo if arr[lo] == target else -1
在二分查找过程中, 可能有目标值不在数组中的情况发生, 在这个过程, 我们只需要找到一个值i
满足
寻找左边界:
∃
i
s
.
t
∀
x
∈
a
r
r
[
i
:
]
x
≥
t
a
r
g
e
t
∧
∀
x
∈
a
r
r
[
:
i
]
,
x
<
t
a
r
g
e
t
寻找右边界:
∃
i
s
.
t
∀
x
∈
a
r
r
[
:
i
]
x
≤
t
a
r
g
e
t
∧
∀
x
∈
a
r
r
[
i
:
]
,
x
>
t
a
r
g
e
t
\text{寻找左边界: } \\ \exists i\ s.t\quad\forall x\in arr[i:]\ x \ge target \\ \land \forall x\in arr[:i],\ x\lt target \\ \text{寻找右边界: } \\ \exists i\ s.t\quad\forall x\in arr[:i]\ x \le target \\ \land \forall x\in arr[i:],\ x\gt target
寻找左边界: ∃i s.t∀x∈arr[i:] x≥target∧∀x∈arr[:i], x<target寻找右边界: ∃i s.t∀x∈arr[:i] x≤target∧∀x∈arr[i:], x>target
left = 0, right = length
left == right
right = mid - 1
left = mid
left = 0, right = length
left == right
right = mid
left = mid+1
def leftBisect(arr: List[int], target: int): lo, hi = 0, len(arr) while lo < hi: mid = (lo+hi)//2 if arr[mid] < target: lo = mid+1 else: hi = mid return lo def rightBisect(arr: List[int], target: int): lo, hi = 0, len(arr) while lo < hi: mid = (lo+hi)//2 if target < arr[mid]: hi = mid else: lo = mid+1 return lo
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。