【蓝桥杯】二分查找

发布于:2025-04-12 ⋅ 阅读:(35) ⋅ 点赞:(0)

1. 题目

题目描述
给定一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值,返回 [-1, -1]

要求

  1. 必须使用二分查找算法

  2. 时间复杂度必须是 O(log n)

  3. 不能使用线性扫描或内置函数直接查找(如 index()find() 等)

示例

输入: nums = [5,7,7,8,8,10], target = 8
输出: [3,4]

输入: nums = [5,7,7,8,8,10], target = 6
输出: [-1,-1]

输入: nums = [], target = 0
输出: [-1,-1]

2. 思路

1. 为什么必须用二分查找

  • 题目明确要求时间复杂度 O(log n)

  • 线性扫描法(O(n))不符合要求

  • 数组已排序,是二分查找的典型应用场景

2. 问题分解

需要解决两个子问题:

  1. 找到 target 的第一个位置(左边界)

  2. 找到 target 的最后一个位置(右边界)

3. 二分查找变种

  • 标准二分查找找到目标值就返回

  • 本题需要继续查找边界,因此需要修改标准算法

4. 算法步骤

  1. 实现查找左边界的二分查找

    • 当 nums[mid] >= target 时继续向左搜索

    • 最后检查找到的位置是否等于 target

  2. 实现查找右边界的二分查找

    • 当 nums[mid] <= target 时继续向右搜索

    • 最后检查找到的位置是否等于 target

  3. 组合两个结果

3. 代码

nums=list(map(int,input().split()))
target=int(input())
"""
在排序数组中查找元素的第一个和最后一个位置
param nums: 非递减排序的整数数组
param target: 要查找的目标值
return: 目标值的起始和结束位置 [start, end],如果不存在返回 [-1, -1]
"""
def find_left():
    left, right = 0, len(nums) - 1
    while left <= right:
        mid = (left + right) // 2
        if nums[mid] >= target:
            right = mid - 1
         else:
            left = mid + 1
    return left if left < len(nums) and nums[left] == target else -1
    
def find_right():
    left, right = 0, len(nums) - 1
    while left <= right:
        mid = (left + right) // 2
        if nums[mid] <= target:
            left = mid + 1
        else:
            right = mid - 1
    return right if right >= 0 and nums[right] == target else -1
    
if not nums:
    return [-1, -1]
    
left_pos = find_left()
right_pos = find_right()
    
print([left_pos, right_pos])

网站公告

今日签到

点亮在社区的每一天
去签到