day5-python之遞歸函數

1、初識遞歸

一、遞歸的定義

在一個函數裏再調用這個函數自己,這種魔性的使用函數的方式就叫作遞歸。python

二、遞歸的深度

遞歸函數若是不受到外力的阻止會一直執行下去。每一次函數調用都會產生一個屬於它本身的名稱空間,若是一直調用下去,會形成名稱空間佔用太多內存。因而python爲了杜絕相似內存溢出現象,強制將遞歸層數控制在了998。算法

def func():
    print(1)
    func()
func()   # 遞歸最大深度爲:998

由此能夠看出,未報錯以前能看到的最大數字就是997。997是python爲了程序的內存優化所設定的一個默認值,能夠經過一些手段修改:函數

# 修改遞歸的最大深度(儘可能不要改)
import sys
sys.setrecursionlimit(1000000)   # 3221
def foo(n):
    print(n)
    n += 1
    foo(n)
foo(1)

能夠經過這種方式來修改遞歸的最大深度,剛剛將python容許的遞歸深度設置爲了10W,實際能夠達到的深度取決於計算機的性能。不推薦修改這個默認的遞歸深度,若是用997層遞歸都沒能解決的問題,要麼不適合遞歸解決,要麼代碼寫的太爛。
江湖流傳這樣一句話:人理解循環,神理解遞歸。
sys模塊:包含全部和python相關的設置和方法。
遞歸就是本身調用本身。
遞歸須要有一箇中止條件,若是沒有中止條件就會報錯。性能

2、再談遞歸

例1:階乘

6!優化

65432*1code

def fn(n):
    if n == 1:return 1
    return n*fn(n-1)
print(fn(6))

執行過程:
def fn(6):
return 6*fn(5)blog

def fn(5):
    return 5*fn(4)

def fn(4):
    return 4*fn(3)

def fn(3):
    return 3*fn(2)

def fn(2):
    return 2*fn(1)

def fn(1):
    return 1

例2:猜小明年齡

小明是新來的同窗,麗麗問他多少歲了。排序

他說:我不告訴你,可是我比滔滔大兩歲。遞歸

滔滔說:我也不告訴你,我比曉曉大兩歲內存

曉曉說:我也不告訴你,我比小星大兩歲

小星也沒有告訴他說:我比小華大兩歲

最後小華說,我告訴你,我今年18歲了

知道小華的,就會知道小星的,知道小星的就會知道曉曉的,以此類推,就會知道小明的年齡。這個過程接近遞歸思想。

  • 小華 18+2
  • 小星 20+2
  • 曉曉 22+2
  • 滔滔 24+2
  • 小明 26+2

用序號表示:

age(5) = age(4)+2
age(4) = age(3) + 2 
age(3) = age(2) + 2
age(2) = age(1) + 2
age(1) = 18

寫成代碼:

def age(n):
    if n == 1:
        return 18
    else:
        return age(n - 1) + 2
ret = age(6)
print(ret)

例3: 一個數除2,知道不能整除

def cal(num):
    if  num%2==0:     #先判斷能不能整除
        num=num//2
        return cal(num)
    else:
        return num
print(cal(8))

例4:一個數能夠整除2,就整除。不能整除就*3+1

def func(num):
    print(num)
    if num==1:
        return
    if num%2==0:
        num=num//2
    else:
        num=num*3+1
    func(num)
func(5)

3、二分查找算法

# 人類的算法(靈活)

9999=99(100-1)=9900-99=9801

# 計算機的算法(死板)
99*99

計算一些比較複雜的問題,所採用的在空間上(內存裏)或者時間上(執行時間)更有優點的方法

# 排序 500W個數:快速排序、堆排序、冒泡排序

# 查找

l = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]

# 簡單版二分法
l = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]
def cal(l,num=66):
    length = len(l)
    mid = length//2
    if num > l[mid]:
        l = l[mid+1:]
        cal(l,num)
    elif num < l[mid]:
        l = l[:mid]
        cal(l, num)
    else:
        print('找到了',l[mid],mid)
cal(l,66)


# 升級版二分法
def cal(l,num,start=0,end=None):
    # if end is None:end = len(l)-1
    end = len(l)-1 if end is None else end
    if start <= end:
        mid = (end - start)//2 + start
        if l[mid] > num :
            return cal(l, num, start, mid-1)
        elif l[mid] < num:      # 13  24
            return cal(l,num,mid+1,end)
        else:
            return mid
    else:
        return None
l = [2,3,5,10,15,16,18,22,26,30,32,35,41,42,43,55,56,66,67,69,72,76,82,83,88]
print(cal(l,56))
相關文章
相關標籤/搜索