[!NOTE] 重点
- 循环控制用
left <= right还是left < right?- 符合判断条件
if numbers[middle] > target时,使用right = middle还是right = middle + 1?
题目描述
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
二分法如何查找
开始写二分法时,常规会定义两种区间方式:左闭右闭 [left, right]、左闭右开 [left, right)。
-
左闭右闭
[left, right]:target每次查询的区间是[left, right]。
# 边界初始值 left, right = 0, len(nums) - 1 # right 节点的边界要等于数组的 index # 循环判断 while left <= right: # 每次都在 [left, right] 区间内查询 mid = (left + right) // 2 # 计算中间元素的下标 # 条件判断 if target > nums[mid]: left = mid + 1 elif target < nums[mid]: right = mid - 1 # 右闭合区间,所以每次缩小区间无须覆盖上一次循环的区域 -
左闭右开
[left, right):target每次查询的区间是[left, right)。
# 边界初始值 left, right = 0, len(nums) # 由于开放区间 right 边界要等于数组的长度 # 循环判断 while left < right: # 每次都在 [left, right) 区间内查询 mid = (left + right) // 2 # 计算中间元素的下标 # 条件判断 if target > nums[mid]: left = mid + 1 elif target < nums[mid]: right = mid # 右开区间,每次缩小区间,需要 mid 做右区间,如果 -1,会造成查找覆盖不全
代码实例(左闭右闭)
from typing import List
class Solution:
def search(self, nums: List[int], target: int) -> int:
"""
二分查找算法,在有序数组 nums 中搜索目标值 target 的下标。
:param nums: 有序整型数组
:param target: 目标值
:return: 如果目标值存在,返回其下标;否则返回 -1
"""
left, right = 0, len(nums) - 1 # 初始化左右边界
while left <= right:
mid = (left + right) // 2 # 计算中间元素的下标
mid_value = nums[mid]
if mid_value == target:
return mid # 目标值等于中间值,返回中间值的下标
if mid_value < target:
left = mid + 1 # 如果目标值大于中间值,在右半部分继续查找
else:
right = mid - 1 # 如果目标值小于中间值,在左半部分继续查找
return -1 # 没有找到目标值,返回 -1
# 示例用法
if __name__ == "__main__":
solution = Solution()
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9]
target = 5
result = solution.search(nums, target)
if result != -1:
print(f"目标值 {target} 在数组中的下标是 {result}")
else:
print(f"目标值 {target} 不在数组中")