常用算法之二分查找

二分查找简单又常用,但只能针对已经排序好的数据。时间复杂度为O(logN), 变种挺多。

# 二分查找

from typing import List

# 查找等于v的值
def bsearch(arr: List[int], v):
    low = 0
    high = len(arr) - 1
    while low <= high:
        mid = low + ((high - low) >> 1)
        if arr[mid] == v:
            return mid
        elif arr[mid] < v:
            low = mid + 1
        else:
            high = mid - 1
    return -1

# 查找第一个等于v的值
def bsearch_first(arr: List[int], v):
    low = 0
    high = len(arr) - 1
    while low <= high:
        mid = low + ((high - low)>>1)
        if arr[mid] >= v:
            high = mid - 1
        else:
            low = mid + 1

    if low < len(arr) and arr[low] == v:
        return low
    return -1

# 和上面一样,但是好理解
# def bsearch_first(arr: List[int], v):
#     low = 0
#     high = len(arr) - 1
#     while low <= high:
#         mid = low + ((high - low)>>1)
#         if arr[mid] > v:
#             high = mid - 1
#         elif (arr[mid] < v):
#             low = mid + 1
#         else:
#             if mid == 0 or (arr[mid - 1]) != v:
#                 return mid
#             else:
#                 high = mid - 1

#     return -1
    

# 查找最后一个等于v的值
def bsearch_last(arr: List[int], v):
    low = 0
    high = len(arr) - 1
    while low <= high:
        mid = low + ((high - low) >> 1)
        if arr[mid] <= v:
            low = mid + 1
        else:
            high = mid - 1
    
    if high >= 0 and arr[high] == v:
        return high
    return -1

# 和上面一样但是好理解
# def bsearch_last(arr: List[int], v):
#     low = 0
#     high = len(arr) - 1
#     while low <= high:
#         mid = low + ((high - low) >> 1)
#         if arr[mid] < v:
#             low = mid + 1
#         elif arr[mid] > v:
#             high = mid - 1
#         else:
#             if mid == len(arr) - 1 or arr[mid + 1] != v:
#                 return mid
#             else:
#                 low = mid + 1

#     return -1
    
# 查找第一个大于等于v的值
def bsearch_first_ge(arr:List[int], v):
    low = 0
    high = len(arr) - 1
    while low <= high:
        mid = low + ((high - low) >> 1)
        if arr[mid] >= v:
            if mid == 0 or arr[mid - 1] < v:
                return mid
            else:
                high = mid - 1
        else:
            low = mid + 1
    
    return -1

# 查找最后一个小于等于v的值
def bsearch_last_le(arr:List[int], v):
    low = 0
    high = len(arr) - 1
    while low <= high:
        mid = low + ((high - low) >> 1)
        if arr[mid] > v:
            high = mid - 1
        else:
            if mid == len(arr) - 1 or arr[mid + 1] > v:
                    return mid
            else:
                low = mid + 1

    return -1


# 搜索升序排序旋转数组,比如[4,5,6,1,2,3] 力扣 id: 33
def bsearch_rotate_arr(arr:List[int], v):
    low = 0
    high = len(arr) - 1
    while low <= high:
        mid = low + ((high - low) >> 1)
        if arr[mid] == v:
            return mid
        elif arr[mid] < arr[low]:
            # mid及之后是有序的
            if v >= arr[mid] and v <= arr[high]:
                low = mid
            else:
                high = mid - 1
        else:
            # mid之前是有序的
            if v >= arr[low] and v <= arr[mid]:
                high = mid
            else:
                low = mid + 1
    return -1
        
arr = [1,2,3,4,4,4,4,5,6]
print(bsearch(arr, 4))
print(bsearch_first(arr, 4))
print(bsearch_last(arr, 4))
print(bsearch_first_ge(arr, -10))
print(bsearch_last_le(arr, 100))
print('------------')
print(bsearch_rotate_arr([4,5,6,1,2,3,4], 3))

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值