代码随想录算法训练营第一天 (1) | 704. 二分查找

81 阅读2分钟

[!NOTE] 重点

  1. 循环控制用 left <= right 还是 left < right
  2. 符合判断条件 if numbers[middle] > target 时,使用 right = middle 还是 right = middle + 1

题目描述

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

二分法如何查找

开始写二分法时,常规会定义两种区间方式:左闭右闭 [left, right]、左闭右开 [left, right)

  1. 左闭右闭 [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  # 右闭合区间,所以每次缩小区间无须覆盖上一次循环的区域
    
  2. 左闭右开 [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} 不在数组中")