LeetCode_Python_二分查找算法

算法要求

  1. 顺序存储结构
  2. 元素大小有序

二分查找过程

  1. 将元素排序;
  2. 将中间位置记录的这个元素与目标元素比较;
    2.1 如果相同,则查找成功;
    2.2 否则将元素分为前、后两部分,如果目标元素相比查找元素在左,则更新右边界;如果目标元素相比查找元素在右,则更新左边界;
    2.3 重复步骤2

如何更新左右边界

  1. 查找区间为 [left, right],循环条件为 left <= right;左右分别更新为 mid+1、mid-1
  2. 查找区间为 [left, right),循环条件为 left < right;左右分别更新为 mid+1、mid

时间复杂度

二分查找过程的时间复杂度是O(n),其中 n 是元素个。每次查找都缩短一半的长度。

案例

type1:常规对比中间元素

367. 有效的完全平方数

def isPerfectSquare(num):
    left,right=0,num
    while left<=right:
        mid=(left+right)//2
        if mid*mid==num:
            return True
        elif mid*mid<num:
            left=mid+1
        else:
            right=mid-1
    return False

167. 两数之和 II - 输入有序数组

def twoSum(numbers, target):
    n = len(numbers)
    for i in range(n):
        tmp = target - numbers[i]
        left,right=i+1, n-1
        while left<=right:
            mid=(left+right)//2
            if numbers[mid]==tmp:
                return [i+1, mid+1]
            elif numbers[mid]>tmp:
                right=mid-1
            else:
                left=mid+1
    return [-1,-1]

33. 搜索旋转排序数组

def search(nums: List[int], target: int):
    left,right=0,len(nums)-1
    while left<=right:  
        mid=(left+right)//2
        if nums[mid]==target:
            return mid
        elif nums[left]<=nums[mid]:     
            if nums[left]<=target<=nums[mid]:
                right=mid-1
            else:
                left=mid+1
        else:
            if nums[mid]<=target<=nums[right]:
                left=mid+1
            else:
                right=mid-1
    return -1    

type2:跳出循环时的左边界

跳出循环时,left 满足 right 更新时 if 后的条件, left-1 满足满足 left 更新时 if 后的条件

69. x 的平方根

def findSqrt(x):
    left,right=0,x
    while left<=right:
        mid=(left+right)//2
        if mid*mid<=x:
            left=mid+1
        else:
            right=mid-1
    #跳出循环时 left>right,说明上一个更新的是 left,即(left-1)*(left-1)<=x;又 right*right>x,所以left*left>x,因此 left-1 就是要查找的目标数
    return left-1  

35. 搜索插入位置

给定一个排序数组nums和一个目标值target,返回目标值索引。如果不存在,返回它将会被按顺序插入的位置。

def searchInsert(nums, target):
    left,right=0,len(nums)-1
    while left<=right:
        mid=(left+right)//2
        if nums[mid]==target:
            return mid
        elif nums[mid]<target:
            left=mid+1
        else:
            right=mid-1
    #跳出循环时后,nums[left-1]<target & nums[right]>target i.e nums[left]>target,因此target要放在left位置
    return left  

type3:第一个和最后一个位置

34. 在排序数组中查找元素的第一个和最后一个位置

def searchRange(nums: List[int], target: int):
    def binarySearch(condition):
        left, right = 0, len(nums)-1
        while left <=  right:
            mid = (left+right)//2
            if condition(nums[mid], target):
                right = mid-1
            else:
                left = mid+1
        return left
    
    start = binarySearch(lambda x,y: x >= y)
    end = binarySearch(lambda x,y: x > y) - 1
    
    return [start, end] if start<=end else [-1,-1]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值