二分模板

0X00 模板

模板一

# nums 是一个 slice
# left right 是下标
# target 是要选择的元素
left, right = 0, len(nums) - 1
while left < right:
    mid = left + (right - left) // 2
    if target == nums[mid]:
        # 让 left 指向最后的答案
        left = mid
        break
    elif target > nums[mid]:
        left = mid + 1
    else:
        right = mid
        
      

模板二

left, right = 0, len(nums) - 1
while left <= right:
    mid = left + (right - left) // 2
    if target == nums[mid]:
        # 让 left 指向最后的答案
        left = mid
        break
    elif target > nums[mid]:
        left = mid + 1
    else:
        right = mid - 1

0X01 注意事项

  • mid = left + (right - left) // 2 这是一个什么写法

确实,在一般情况下, 这个写法与 mid = (right + left) // 2 一致, 但是在其他语言中两个 int 相加是会越界的,但是这样写不会越界

  • 模板 1 和模板 2 有什么区别

首先 left 一定要加 1 因为不加 1 就会陷入死循环中 对于能找到的元素, left 是最后的答案

关键是不能找到元素的情况 如果不能找到对于模板 1:

最后的情况一定是剩下两个元素,

  • 假设 target 大于所有元素
target = 3
[1, 2]

最后 left = right = 1

  • 假设 target 小于所有元素
target = -1
[1, 2]

最后 left = right = 0

  • 假设 target 是一个中间值
target = 2
[1, 3]

left = right = 1

所以 left 所指的元素比 target 并不是有什么特殊的性质

但是模板二不一样: left 就是要插入的位置

可以靠这个题得到验证:

35. 搜索插入位置

模板 1 主要用来范围查找, 模板 2 主要用来下标查找

  • 时间复杂度

如果 nums 里面有重复元素,那么时间复杂度就有可能是 O(n)

0X02 相关题目

  • 34. Find First and Last Position of Element in Sorted Array

  • 35. Search Insert Position

  • 704. Binary Search

  • 981. Time Based Key-Value Store

你可能感兴趣的:(二分模板)