py_22 二分法(递归的一种运用)

2020-08-20  本文已影响0人  阿登20
# 一、二分法
for循环遍历查找 效率不高。
 使用二分法的大前提:`有序序列类型是从小到大排列`  list.sort()将列表升序
假设我找的那个值比中间那个值大,左侧就不用找了。
再从剩余的区域中间值比较,无限重复这个过程直到找到为止。二分法是递归一种运用
l=[1,2,10,30,33,99,101,200,301,402]
二分法start stop 区间查找。代码封装如下
def search(num,l,start=0,stop=len(l)-1):
    if start <= stop:
        mid=start+(stop-start)//2
        print('start:[%s] stop:[%s] mid:[%s] mid_val:[%s]' %(start,stop,mid,l[mid]))
        if num > l[mid]:
            start=mid+1
            # search(num, l, start, stop) 
        elif num < l[mid]:
            stop=mid-1
            # search(num, l, start, stop)
        else:
            print('find it',mid)
            return
        search(num,l,start,stop)
    else: #如果stop > start则意味着列表实际上已经全部切完,即切为空
        print('not exists')
        return

search(301,l,3,9)

一、二分法

算法之二分法:大前提值是按照从小打到排列

需求:有1个按照从小到大顺序排列的数字列表
需要从该数字列表中找到我们想要的那个一个数字
如何做更高效?

方案一:for循环遍历查找

for num in l:
    if num ==13:
        print("找到了")
        break

方案二:二分法

假设我找的那个值比中间那个值大,左侧就不用找了。
再从剩余的区域中间值比较,无限重复这个过程直到找到为止

# 要找的find_num =13
find_num = 13
mid_value = "先找到中间的值"

if find_num > mid_value:
    # 接下来的查找应该是在右半部分
    # 列表 = 列表切片右半部分
    # 本身的代码(列表)
    pass
elif find_num < mid_value:
    # 接下来的查找应该是在右半部分
    # 列表 = 列表切片左半部分
    # 本身的代码(列表)
    pass
else:
    print("找到了")

# ---------------------------
# 1.把代码先缩进在一个函数里
def binary_search():
    # 要找的find_num =13
    find_num = 13
    mid_value = "先找到中间的值"

    if find_num > mid_value:
    # 接下来的查找应该是在右半部分
    # 列表 = 列表切片右半部分
    # 本身的代码(列表)
        pass
    elif find_num < mid_value:
    # 接下来的查找应该是在右半部分
    # 列表 = 列表切片左半部分
    # 本身的代码(列表)
        pass
    else:
        print("找到了")
        
# 2. 优化代码:函数参数

def binary_search(find_num,list_num):
    """
    find_num: 要找的值
    list_num: 从哪里找
    """

    if len(list_num) ==0:
        print("没找到")
        return
    mid_index = len(list_num)//2
    mid_value = list_num[mid_index]

    if find_num > mid_value:
        list_num = list_num[mid_index + 1:]
        binary_search(find_num, list_num)
    elif find_num < mid_value:
        list_num = list_num[:mid_index]
        binary_search(find_num, list_num)
    else:
        print("找到了")

l = [1]
binary_search(3,l)      
        

二分法start stop 区间查找

image.png
l=[1,2,10,30,33,99,101,200,301,402]

def search(num,l,start=0,stop=len(l)-1):
    if start <= stop:
        mid=start+(stop-start)//2
        print('start:[%s] stop:[%s] mid:[%s] mid_val:[%s]' %(start,stop,mid,l[mid]))
        if num > l[mid]:
            start=mid+1
            # search(num, l, start, stop) 
        elif num < l[mid]:
            stop=mid-1
            # search(num, l, start, stop)
        else:
            print('find it',mid)
            return
        search(num,l,start,stop)
    else: #如果stop > start则意味着列表实际上已经全部切完,即切为空
        print('not exists')
        return

search(301,l,3,9)

案例: 二分法,找到了返回True没找到返回False

如果 用递归函数 我们要最终获取返回值return,需要注意的是:返回值 return 递归函数调用
原因是 你不知道什么时候递归结束。只有将下一次递归的返回值作为当前的返回值,最终才会得到最后一次递归的返回值,
 依次递推回来才会知道调用函数的返回值。
案例: 二分法,找到了返回True没找到返回False

def binary_search(find_num,list_num):
    """
    find_num: 要找的值
    list_num: 从哪里找
    """

    if len(list_num) ==0:
        print("没找到")
        return False
    mid_index = len(list_num)//2
    mid_value = list_num[mid_index]

    if find_num > mid_value:
        list_num = list_num[mid_index + 1:]
        return binary_search(find_num, list_num)
    elif find_num < mid_value:
        list_num = list_num[:mid_index]
        return binary_search(find_num, list_num)
    else:
        print("找到了")
        return True

l = [2,4,6,8,9,10,33,55,77,87,89,90,233]

print(binary_search(11,l))  # False
pass
上一篇下一篇

猜你喜欢

热点阅读