zoukankan      html  css  js  c++  java
  • 递归与二分法

    一、定义

    递归调用是函数嵌套调用的一种特殊形式,函数在调用时,直接或间接调用了自身,就是递归调用

    #直接调用本身
    def f1():
        print('from f1')
        f1()
    f1()
    
    #间接调用本身
    def f1():
        print('from f1')
        f2()
    
    def f2():
        print('from f2')
        f1()
    f1()
    
    # 调用函数会产生局部的名称空间,占用内存,因为上述这种调用会无需调用本身,python解释器的内存管理机制为了防止其无限制占用内存,对函数的递归调用做了最大的层级限制
    四 可以修改递归最大深度
    
    import sys
    sys.getrecursionlimit()
    sys.setrecursionlimit(2000)
    
    def f1(n):
        print('from f1',n)
        f1(n+1)
    f1(1)
    
    虽然可以设置,但是因为不是尾递归,仍然要保存栈,内存大小一定,不可能无限递归,而且无限制地递归调用本身是毫无意义的,递归应该分为两个明确的阶段,回溯与递推
    
    详解
    释义

    二、递归调用应该分为两个明确的阶段:递推,回溯 

    #1、递归调用应该包含两个明确的阶段:回溯,递推
        回溯就是从外向里一层一层递归调用下去,
            回溯阶段必须要有一个明确地结束条件,每进入下一次递归时,问题的规模都应该有所减少(否则,单纯地重复调用自身是毫无意义的)
    
        递推就是从里向外一层一层结束递归
    
    #2、示例+图解。。。
    # salary(5)=salary(4)+300
    # salary(4)=salary(3)+300
    # salary(3)=salary(2)+300
    # salary(2)=salary(1)+300
    # salary(1)=100
    #
    # salary(n)=salary(n-1)+300     n>1
    # salary(1) =100                n=1
    
    def salary(n):
        if n == 1:
            return 100
        return salary(n-1)+300
    
    print(salary(5))
    

    三、递归示例

    # 例1:
    def foo():
        print('from foo')
        foo()
    
    foo()
    
    import sys
    print(sys.getrecursionlimit())
    sys.setrecursionlimit(2000)
    
    # 例2:
    def foo():
        print('from foo')
        bar()
    
    def bar():
        print('from bar')
        foo()
    
    foo()
    示例

    四、递归总结

    # 递归调用有两个阶段
    # 1、回溯:一层一层地递归调用下去
    # 2、递推:在某一层结束递归调用,开始向上一层一层地返回

    #python中的递归
    python中的递归效率低,需要在进入下一次递归时保留当前的状态,在其他语言中可以有解决方法:尾递归优化,即在函数的最后一步(而非最后一行)调用自己,尾递归优化:http://egon09.blog.51cto.com/9161406/1842475
    但是python又没有尾递归,且对递归层级做了限制
    #总结递归的使用:
    1. 必须有一个明确的结束条件
    2. 每次进入更深一层递归时,问题规模相比上次递归都应有所减少
    3. 递归效率不高,递归层次过多会导致栈溢出(在计算机中,函数调用是通过栈(stack)这种数据结构实现的,每当进入一个函数调用,栈就会加一层栈帧,每当函数返回,栈就会减一层栈帧。由于栈的大小不是无限的,所以,递归调用的次数过多,会导致栈溢出)
     
    五、二分法
    想从一个按照从小到大排列的数字列表中找到指定的数字,遍历的效率太低,用二分法(算法的一种,算法是解决问题的方法)可以极大低缩小问题规模
    六、二分法应用示例:
    l=[1,2,10,30,33,99,101,200,301,311,402,403,500,900,1000] #从小到大排列的数字列表
    
    def search(n,l):
        print(l)
        if len(l) == 0:
            print('not exists')
            return
        mid_index=len(l) // 2
        if n > l[mid_index]:
            #in the right
            l=l[mid_index+1:]
            search(n,l)
        elif n < l[mid_index]:
            #in the left
            l=l[:mid_index]
            search(n,l)
        else:
            print('find it')
    
    
    search(3,l)
    
    实现类似于in的效果
    示例1
    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
            elif num < l[mid]:
                stop=mid-1
            else:
                print('find it',mid)
                return
            search(num,l,start,stop)
        else: #如果stop > start则意味着列表实际上已经全部切完,即切为空
            print('not exists')
            return
    
    search(301,l)
    
    实现类似于l.index(30)的效果
    示例2
    nums=[-3,11,13,25,37,39,43,52,77,84,91]
    
    def search(list1,find_num):
        print(list1)
        if len(list1) == 0:
            print('not exists')
            return
    
        mid_index = len(list1) // 2
        if find_num > list1[mid_index]:
            # on the right
            search(list1[mid_index+1:],find_num)
        elif find_num < list1[mid_index]:
            # on the left
            search(list1[:mid_index],find_num)
        else:
            print('find it')
    
    search(nums,85)
    示例3
     
  • 相关阅读:
    冲刺第一天(补发)
    进度条05
    npm start问题
    Spring Boot 默认配置无法访问静态资源
    Spring Boot 返回Html界面
    阿里云配置tomcat后不能访问问题
    Spring Boot Web开发中Thymeleaf模板引擎的使用
    tomcat官网改版后下载方式
    Ubuntu16.04进入无限登录状态的解决办法
    Ubuntu16.04安装MySql5.7
  • 原文地址:https://www.cnblogs.com/datatool/p/13508675.html
Copyright © 2011-2022 走看看