算法套路-二分查找

目录

 

1 查找到了就返回

2 查找左边界

3 查找右边界

4 旋转数组

4.1 找旋转数组中的最小值

4.2 找旋转数组中的特定值

 


二分查找最容易出错的就是边界条件的处理。在遇到这个问题,出错并纠结了很多次后,终于下定决心攻克这个问题,让下次遇到二分问题能够游刃有余。

1 查找到了就返回

这个是最简单的,中间值大于target就往左,小于target就往右,等于target就找到了。

leetcode例题:69. x 的平方根

2 查找左边界

比如a=[2,3,3,4,6],寻找第一个值为3的下标,

开始left=0,right=4,mid=2,第一次找到2下标,

right=2,left=0,mid=1,也就是说找到了一个值为3的下标,不知道它是不是第一个,就把它放在右端,

若前面还有值为3的,又把前面的设置为右端,然后right=1

终止条件有些人习惯left<=right,这样循环结束时left=right+1。但我还是喜欢left<right这个形式,这样循环结束时left==right,然后判断nums[left]或nums[right]是否是target,如果是就找到了, 不是就是target不存在。

class Solution:
    def minEatingSpeed(self, nums: List[int], target: int) -> int:
        left,right=1,len(nums)-1
        while left<right:
            mid=(left+right)//2#mid值偏左
            if nums[mid]>=target: 
              	right=mid#因为找左边界,对可能的右边界就宽容
            else: 
                left=mid+1
        return left

leetcode例题:

278. 第一个错误的版本

875. 爱吃香蕉的珂珂

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

3 查找右边界

class Solution:
    def minEatingSpeed(self, nums: List[int], target: int) -> int:
        left,right=1,len(nums)-1
        while left<right:
            mid=(left+right+1)//2#mid值偏右
            if nums[mid]<=target: 
              	left=mid#因为找右边界,对可能的左边界就宽容
            else: 
                right=mid-1
        return left

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

4 旋转数组

4.1 找旋转数组中的最小值

思路:

如果nums[mid]<nums[right],说明右边有序,最小值不在mid上就在左边,所以right=mid

如果nums[mid]>nums[right],说明左边有序,最小值在右边,left=mid+1

如果nums[mid]==nums[right],不能判断哪边有序,right-=1

无重复数

153. 寻找旋转排序数组中的最小值

有重复数

154. 寻找旋转排序数组中的最小值 II

4.2 找旋转数组中的特定值

81. 搜索旋转排序数组 II

思路:

  • 如果nums[mid]<nums[right],说明右边有序,target不在右边就在左边

  • 如果nums[mid]>nums[right],说明左边有序,target不在左边就在右边

  • 如果nums[mid]==nums[right],不能判断哪边有序,right-=1即可

#找旋转数组中的特定值是否存在代码 
class Solution:
    def search(self, nums: List[int], target: int) -> bool:
        left,right=0,len(nums)-1
        mid=0
        if len(nums)==0:return False
        while left<right:
            mid=(left+right)//2
            if nums[mid]==target:return True
            if nums[mid]<nums[right]:
                if target>nums[mid] and target<=nums[right]:
                    left=mid+1
                else:
                    right=mid-1
            elif nums[mid]>nums[right]:
                if target>=nums[left] and target<nums[mid]:
                    right=mid-1
                else:
                    left=mid+1
            else:
                right-=1
        return nums[right]==target

 

猜你喜欢

转载自blog.csdn.net/nanfeizhenkuangou/article/details/110634491