算法思想 从0到1:分治法——二分查找模板小结(三种:第一种基础,推荐掌握第一种,第三种是第二种的变体)

二分查找模板小结(三种:第一种基础,推荐掌握第二种,第三种是第二种的变体)
刷题要总结,以块进行刷题。还有参加周赛,哪里不会学哪块。一个是积累基础,一个是查漏补缺。加油

以力扣704题为例:

题目描述:

在这里插入图片描述

题解:

方法1: 循环条件为left <= right。先看mid处的值与target的关系,如果相等就输出,然后划分为两个区间[left,mid -1],[mid +1,right]

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        #模板一:
        if nums == []:#特例判断
            return -1
        n = len(nums)
        left,right = 0,n-1
        while left <= right:
            mid = left +(right - left) // 2 #中间处下标,向下取整
            if nums[mid] == target:
                return mid
            elif nums[mid] > target:#[left,mid -1]
                right = mid - 1
            else:               #[mid +1,right]
                left = mid + 1
        return -1

方法2: 推荐掌握,循环条件为left < right,循环结束时一定有left = right,最后需要判断nums[left]与target的关系。此有两个版本:(1)mid向下取整,则区间分为[left,mid],[mid+1,right](2)mid向上取整,则区间分为[left,mid-1],[mid,right]
(1)mid向下取整(寻找左端点)
则区间分为[left,mid],[mid+1,right]

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        #模板二:向下取整,
        if nums == []:
            return -1
        n = len(nums)
        left,right = 0,n
        while left < right:
            mid = left + (right - left) // 2#中间处下标,向下取整
            if nums[mid] >= target:#[left,mid]
                right = mid
            else:		#[mid+1,right]
                left = mid + 1
        return left if nums[left] == target else -1

或者:

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        #模板二:向下取整,
        if nums == []:
            return -1
        n = len(nums)
        left,right = 0,n - 1
        while left < right:
            mid = (left + right) >> 1 #中间处下标,向下取整
            if nums[mid] >= target:#[left,mid]
                right = mid
            else:		#[mid+1,right]
                left = mid + 1
        return left if nums[left] == target else -1

(2)mid向上取整(寻找右端点)
则区间分为[left,mid-1],[mid,right]

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        #模板二:向上取整
        if nums == []:
            return -1
        n = len(nums)
        left,right = 0,n
        while left < right:
            mid = left + (right - left +1) // 2#中间处下标,向上取整
            if nums[mid] <= target:#[mid,right]
                left = mid 
            else:  		#[left,mid-1]
                right = mid - 1
        return right if nums[right] == target else -1

或者:

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        #模板二:向上取整
        if nums == []:
            return -1
        n = len(nums)
        left,right = 0,n - 1
        while left < right:
            mid = (left + right + 1) >> 1 #中间处下标,向上取整
            if nums[mid] <= target:#[mid,right]
                left = mid 
            else:  		#[left,mid-1]
                right = mid - 1
        return right if nums[right] == target else -1

方法3:循环条件为left + 1 <right,在循环体中,先判断nums[mid]
和target的大小,相等返回;不相等,返回[left,mid],[mid,right]。最后循环结束时还要再次判断left、right处的值与target是否相等。

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        #模板三:
        if nums == []:
            return -1
        left ,right = 0,len(nums) -1
        while left +1 < right:
            mid = left + (right - left) // 2#向下取整
            if nums[mid] == target:
                return mid
            elif nums[mid] > target:	#[left,mid]
                right = mid
            else:			#[mid,right]
                left = mid
        if nums[left] == target:
            return left
        if nums[right] ==target:
            return right
        return -1

附上:
1、寻找左端点:

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        #找左端点
        left,right = 0,len(nums) - 1
        while left <= right:
            mid = left + (right - left) // 2
            if nums[mid] < target:
                left = mid + 1
            elif nums[mid] > target:
                right = mid - 1
            elif nums[mid] == target:
                right = mid - 1
        return left if nums[left] == target else -1  

2、寻找右端点:

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        #找右端点
        left,right = 0,len(nums) - 1
        while left <= right:
            mid = left + (right - left) // 2
            if nums[mid] < target:
                left = mid + 1
            elif nums[mid] > target:
                right = mid - 1
            elif nums[mid] == target:
                left = mid + 1
        return right if nums[right] == target else -1      

复杂度分析

三种方法的时间复杂度都为O(logN)
空间复杂度都为O(1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值