704.二分查找
题目
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。
示例 1:
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4
示例 2:
输入: nums = [-1,0,3,5,9,12], target = 2
输出: -1
解释: 2 不存在 nums 中因此返回 -1
提示:
你可以假设 nums 中的所有元素是不重复的。
n 将在 [1, 10000]之间。
nums 的每个元素都将在 [-9999, 9999]之间。
注意
题干要素
- 有序数组
- 无重复数组
阶梯注意事项
区间不变
区间的定义就是不变量。要在二分查找的过程中,保持不变量,就是在while寻找中每一次边界的处理都要坚持根据区间的定义来操作,这就是循环不变量规则。
写二分法,区间的定义一般为两种,左闭右闭即[left, right],或者左闭右开即[left, right)。
解法
左闭右闭
class Solution:def search(self, nums: List[int], target: int) -> int:left, right = 0, len(nums) - 1 # 定义target在左闭右闭的区间里,[left, right]while left <= right:middle = left + (right - left) // 2# middle = (left+right)// 2if nums[middle] > target:right = middle - 1 # target在左区间,所以[left, middle - 1]elif nums[middle] < target:left = middle + 1 # target在右区间,所以[middle + 1, right]else:return middle # 数组中找到目标值,直接返回下标return -1 # 未找到目标值
左闭右开
class Solution:def search(self, nums: List[int], target: int) -> int:left, right = 0, len(nums) # 定义target在左闭右开的区间里,即:[left, right)while left < right: # 因为left == right的时候,在[left, right)是无效的空间,所以使用 <middle = left + (right - left) // 2if nums[middle] > target:right = middle # target 在左区间,在[left, middle)中elif nums[middle] < target:left = middle + 1 # target 在右区间,在[middle + 1, right)中else:return middle # 数组中找到目标值,直接返回下标return -1 # 未找到目标值
其他题解
解题思路
「二分查找」是利用数组的有序性,每轮缩窄一半的查找区间(即排除一半元素),直到找到目标值或查找区间为空时返回。
由于每轮可以排除一半元素,因此查找最多循环 log 2 N 次,时间复杂度 O(logN) 。在数据量较大时,「二分查找 O(logN) 」效率大幅高于「线性查找 O(N) 」。
理解二分查找的关键是理解缩窄区间的含义。给定升序数组 nums 和目标值 target ,二分查找流程如下:
定义查找区间: 初始化双指针 i , j 分别指向数组首、尾元素,代表查找区间为闭区间 [i,j] ;
循环二分,缩窄查找区间:
使用向下取整除法,计算区间 [i,j] 的中点 m ;
若 nums[m]<target ,根据数组有序性,易得 target 一定不在闭区间 [i,m] 中,因此执行 i=m+1 ,即将查找区间缩窄至 [m+1,j] ;
若 nums[m]>target , 根据数组有序性,易得 target 一定不在闭区间 [m,j] 中,因此执行 j=m−1 ,即将查找区间缩窄至 [i,m−1] ;
若 nums[m]=target ,说明找到 target ,返回索引 m 即可;
不满足 i≤j 时跳出循环,此时代表无法在数组中找到 target ,因此返回 −1 ;
复杂度分析
时间复杂度 O(logN) : 其中 N 为数组 nums 长度。二分查找使用对数级别时间。
空间复杂度 O(1) : 变量 left , right 使用常数大小空间。
参考:
- https://leetcode.cn/problems/binary-search/solutions/1692151/by-jyd-i7xr
- 代码随想录 https://programmercarl.com