二分搜索-解题思路

129 阅读2分钟

二分搜索

在计算机科学中,二进制搜索,也被称为折半搜索算法,是一种搜索算法,每次搜索都能排除掉一半的不存在目标结果的集合,所以在最坏情况下,经过log(n)log(n)次搜索,得到最终结果。

解题实例

如何将二分搜索以代码的形式,转化为解决某几类问题的利器呢?下面以两种类型的题目为例,总结出一种通用的解题思路。

1.搜索某个值

搜索插入位置

class Solution:
    def searchInsert(self, nums: List[int], target: int) -> int:
        left = 0
        right = len(nums) - 1
        while left <= right:  # 搜索区间为[left, right]
            mid = left + (right - left) // 2
            val = nums[mid]
            if val == target:  # 找到目标值
                return mid
            elif val > target:
                right = mid - 1  # 目标值在mid左侧,更新搜索区间为[left, mid - 1]
            else:
                left = mid + 1  # 目标值在mid右侧,更新搜索区间为[mid + 1, right]
        # 当left=right时,mid=left=right
        # 如果val > target, target应该插入到mid前面(target下标为mid),接着right=mid-1,left=mid跳出循环,结果为left
        # 如果val < target, target应该插入到mid后面(target下标为mid+1),接着left=mid+1,right=mid跳出循环,结果为left
        # 所以最终返回都是left
        return left

2.求左(右)边界值

第一个错误的版本

# The isBadVersion API is already defined for you.
# def isBadVersion(version: int) -> bool:

class Solution:
    def firstBadVersion(self, n: int) -> int:

        left = 1
        right = n
        while left <= right:  # 搜索区间[left, right]
            mid = left + (right - left) // 2
            if isBadVersion(mid):  # 是错误版本,则新区间为[left, mid-1]
                right = mid - 1
            else:  # 不是错误版本,则新区间为[mid+1, right]
                left = mid + 1
        return left

思路总结

可以看出,二分搜索是可以总结出固定的解题思路,快速写出解题代码。

  1. 确定搜索区间为[left,right][left, right],注意是两边都闭的区间(当然也可以是[left,right)[left, right)的区间,不过此时区间的初始值会不同,这个可以自己去想一想)

  2. 缩小区间

    • midmid在所求值左边,下一搜索区间为[left,mid1][left, mid-1]
    • midmid在所求值右边,下一搜素区间为[mid+1,right][mid+1, right]
    • midmid等于所求值,
      • 求确定值则直接返回midmid
      • 求左边界,则归属为第一种情况
      • 求右边界,则归属为第二种情况