递归函数、算法之二分法

递归函数

概念
	函数直接或者间接调用了自己 >>>: 递归调用

# 递归调用:直接调用
# def index():
#     print('from index')
#     index()
# index()

# 递归调用:间接调用
# def index():
#     print('from index')
#     func()
# def func():
#     print('from func')
#     index()
# func()
"""
python中允许函数最大递归调用的次数
    官方给出的限制是1000 用代码去验证可能会有些许偏差(997 998...)
"""
# count = 1
# def index():
#     print('from index')
#     global count
#     count += 1  # count = count + 1
#     print(count)
#     index()
# index()
# import sys
# print(sys.getrecursionlimit())  # 1000  获取递归最大次数
# sys.setrecursionlimit(2000)  # 我们也自定义最大的递归次数
# print(sys.getrecursionlimit())

ps:
    这里可能会有面试官问,你知道python递归的最大次数是多少吗
    	我知道它官方定义的是一千,但是用程序跑的话可能就996,997这样


"""
递归函数真正的应用场景(它的核心有两个)
    1.递推:一层层往下寻找答案
    2.回溯:根据已知条件推导最终结果
递归函数(要符合这两个特征)
    1.每次调用的时候都必须要比上一次简单!!!
    2.并且递归函数最终都必须要有一个明确的结束条件!!!
"""
l1 = [1, [2, [3, [4, [5, [6, [7, [8, [9, [10, ]]]]]]]]]]
# 循环打印出列表中所有的数字
# 1.for循环l1里面所有的数据值
# 2.判断当前数据值是否是数字 如果是则打印
# 3.如果不是则继续for循环里面所有数据值
# 4.判断当前数据值是否是数字 如果是则打印
# 5.如果不是则继续for循环里面所有数据值
# 6.判断当前数据值是否是数字 如果是则打印

'''
如果你的代码是这个雷同且不重复的样子,那么就可以使用递归函数
l1 = [1,[2,[3,[4,[5,[6]]]]]]                    
for i in l1:                                 
    if isinstance(i,int):                       
        print(i)                                
    else:                                       
        for j in i:                             
            if isinstance(j,int):               
                print(j)                        
            else:                               
                for k in j:                     
                    if isinstance(k,int):       
                        print(k)  
'''              
               
def get_num(l1):
    for i in l1:
        if isinstance(i,int):  # 判断某个数据类型属不属于另外一个数据类型的小方法,这个小方法是isinstance,isinstance(i,int)意思就是判断i绑定的数据值是不是int类型
            print(i)		 
        else:
            get_num(i)
get_num(l1)

算法之二分法

什么是算法
	算法就是解决问题的方法
算法永远都在精进 但是很少有最完美的算法
	算法很多时候可能没什么用
    	小公司一般不会有算法工程师 只有大公司才会有
   			算法工程师待遇很高 但是产出很少 甚至几年几十年都没有成果
          有点相当于科研人员
很多大型互联网面试都喜欢问算法
	平时学有余力可以简单看看(临时抱佛脚)
    	二分法 快拍 插入 堆排 链表 双向链表 约瑟夫问题
二分法
	是所有算法里面最简单的算法
    	也有人说二分法不是算法
 ### 假如说现再有一个列表时从左侧开始逐渐升序,从右侧往左逐渐降序,请问,我想得到999这个数字,如何获得?  我们可以使用二分法,就将数据一分为二,取中间的数字和我们想要得到的数字进行比较,如果中间的数字比他大,就在左侧找,比他小就在右侧找。所以二分法,前提是这个数据是有序的,要么升序要么降序,混乱的是不行的
### 算法的优势在于,同样一个问题,它能提供更优更加简略的方法
### 面试的时候面试官可能会让你手写一个算法题,或者问你,如何快速的将一堆数字排序(快排算法),如何插入一个值能符合他原来的规则不受影响(插入算法)
l1 = [11, 23, 32, 45, 65, 78, 90, 123, 432, 467, 567, 687, 765, 876, 999, 1131, 1232]

def get_num(l1, target_num):
    # 添加递归函数的结束条件
    if len(l1) == 0:
        print('不好意思 找不到')
        return
    # 1.先获取数据集中间那个数
    middle_index = len(l1) // 2  ## //是整除,取整除部分  432
    # 拿到中间索引的值
    middle_value = l1[middle_index]
    # 2.判断中间的数据值与目标数据值孰大孰小
    if target_num > middle_value:
        # 3.说明要查找的数在数据集右半边何  如何截取右半边
        right_l1 = l1[middle_index + 1:] # 取从中间右边的一个数到最后一个数
        # 3.1.获取右半边中间那个数
        # 3.2.与目标数据值对比
        # 3.3.根据大小切割数据集
        # 经过分析得知 应该使用递归函数
        print(right_l1)
        get_num(right_l1, target_num)
    elif target_num < middle_value:
        # 4.说明要查找的数在数据集左半边  如何截取左半边
        left_l1 = l1[:middle_index]
        # 4.1.获取左半边中间那个数
        # 4.2.与目标数据值对比
        # 4.3.根据大小切割数据集
        # 经过分析得知 应该使用递归函数
        print(left_l1)
        get_num(left_l1, target_num)
    else:
        print('找到了', target_num)


# get_num(l1, 999)
get_num(l1, 1000)

"""
二分法缺陷
	1.数据集必须是有序的
	2.查找的数如果在开头或者结尾 那么二分法效率更低!!!
"""
posted @ 2023-06-15 16:38  W-Y-N  阅读(16)  评论(0)    收藏  举报