二分查找

原理

二分查找又叫折半查找,从有序列表的初始候选区li[0:n]开始,通过对待查找的值与候选区中间值的比较,可以使候选区减少一半。

如果待查值小于候选区中间值,则只需比较中间值左边的元素,减半查找范围。依次类推依次减半。

二分查找的前提:列表有序
二分查找的有点:查找速度快

二分查找的时间复杂度为:O(logn)

动画演示

动画演示

代码实现

# 代码实现,假设列表元素升序排列
def binary_search(target, li):
    left = 0
    right = len(li) - 1
    while left <= right:
        mid = (left + right) // 2
        if target == li[mid]:		# 刚好找到
            return mid
        elif target < li[mid]:		# 待查值在候选区的左半部分,调整候选区右边界,
            right = mid - 1
        else:						# 待差值在候选区的右半部分,调整候选区左边界
            left = mid + 1
    else:
        return -1

递归实现

使用函数递归调用也可以实现二分查找算法,但不推荐,递归调用本身就需要占用内存(栈区记录递归次数)

基础版:基础版只能判断出待查找的数是否在列表中,不能提供该值在列表中的索引值。

缺点:每次递归都要做列表切片,占用额外内存空间。

def binary_search(li, target):
    # print(li)
    if not li:           # 此处使用if-else判断就相当于递归退出条件了
        print('找不到')
    else:
        mid_index = len(li) // 2
        # print(li[mid_index])
        if target == li[mid_index]:
            print('找到了')
        elif target < li[mid_index]:
            binary_search(li[:mid_index], target)
        elif target > li[mid_index]:
            binary_search(li[mid_index+1:], target)
            
            
          
        
if __name__ == '__main__':

    li = [2,5,7,12,54,89,100]
    binary_search(li, 80) 

强化版:找到后返回其所在的索引值,找不到返回-1。

缺点:函数参数稍微复杂点。

def binary_search_plus(li, target, left, right):
    """
    递归二分查找,找到返回索引值,找不到返回 -1
    :param li: 待查找列表
    :param target: 待查找目标值
    :param left: 索引开始值,0
    :param right: 索引结束值,len(li)-1
    :return: index or -1
    """
    # print(li[left:right+1])
    if left > right:
        return -1   # 找不到返回-1

    mid = (left + right) // 2
    # print(li[mid])
    if target == li[mid]:
        return mid          # 找到返回索引值
    elif target < li[mid]:
        return binary_search_plus(li, target, left, mid-1)
    elif target > li[mid]:
        return binary_search_plus(li, target, mid+1, right)



if __name__ == '__main__':

    li = [2,5,7,12,54,89,100]
    res = binary_search(li, 80)
    print(res)
posted @ 2020-03-06 13:32  the3times  阅读(436)  评论(0编辑  收藏  举报