🍖函數遞歸與二分法

一.函數遞歸

1.什麼是遞歸調用

  • 遞歸調用是函數嵌套調用的一種特殊形式
  • 函數在調用時, 直接或間接調用了自己, 這就是遞歸調用
  • 遞歸的本質就是循環

2.直接和間接調用自己示例

  • 直接調用 : 死循環, 無心義
def f1():
    print('from f1')
    f1()
f1()    # 當超過遞歸最大深度時報錯 "RecursionError"
  • 間接調用
def bar():
    print('sa')
    foo()

def foo():
    print('sds')
    bar()

foo()   # 這樣來回調用無心義, 當超過遞歸最大深度時報錯 "RecursionError"

3.設置遞歸最大深度

  • 調用函數會產生局部的名稱空間,佔用內存,由於上述這種調用會無休止調用自己
  • 爲了防止其無限制佔用內存,python 解釋器的內存管理機制對函數的遞歸調用作了最大的層級限制

ps : 雖然能夠修改, 但應該有邊界, 不可能無限制的遞歸, 那樣無心義, 遞歸應分爲明確的兩個階段 (回溯, 遞推)python

import sys
print(sys.getrecursionlimit())   # 默認1000
sys.setrecursionlimit(2000)      # 能夠改
print(sys.getrecursionlimit())   # 2000

4.遞歸的兩個階段

  • 回溯

🍔回溯就是從外向裏層一層一層遞歸調用下去
🍔回溯階段必需要有一個明確的結束條件
🍔每次進入下一次遞歸時, 問題的規模應該減小,不然單純的無限的遞歸毫無心義
  • 遞推

🍔遞推就是從裏到外一層一層結束遞歸
🔰示例
age(5)=age(4)+2
age(4)=age(3)+2
age(3)=age(2)+2
age(2)=age(1)+2
age(1)=18  # 求 age(5) 的值

🔰先研究表達式如何成立
age(n) = age(n-1) + 2
age(1) = 18

🔰寫函數計算
def age(n):
    if n == 1:
        return 18
    return age(n-1)+2  # age(4)+2 = age(3)+2+2 = age(2)+2+2+2 = age(1)+2+2+2+2 = 18+8 = 26
print(age(5))          # 26

5.總結

  • 遞歸必定要有一個明確的結束條件
  • 每次進入下一次遞歸, 問題的規模都應該減小
  • 在 Python 中沒有尾遞歸優化

🔰什麼是問題規模減小簡單示例:算法

🍔將不是列表的值打印出來
l = [1, [2, [3, [4, [5, [6, [7, [8, [9]]]]]]]]]

def outter(itmes):
    for line in itmes:
        if type(line) is not list:
            print(line)
        else:
            outter(line)

outter(l)  # 1,2,3,4,5,6,7,8,9

二. 二分法

1.什麼是算法

  • 算法是解決問題的方法
  • 二分法就是一種算法

2.二分法示例

  • 想要從一個從小到大排列的成千上萬個值中找到指定的值
  • 若是使用遍歷的話效率過低
  • 那麼二分法就能夠極大的縮小問題的規模, 以次來提升效率
nums = [-23,-2,4,5,8,90,234,345,467,786,978,8900]  # 從小到大排列
def check(num,l):
    if len(l) == 0:
        print("沒有值")
        return
    if not num in l:
        print("此數字不存在")
        return
    mid_num = len(l) // 2
    if num > l[mid_num]:   # 說明在中間值得右邊
        l = l[mid_num+1:]  # 使用切片將右邊的值重新賦值給 l
        check(num,l)       # 遞歸
    elif num < l[mid_num]: # 說明在中間值得右邊
        l = l[:mid_num]    # 使用切片將右邊的值重新賦值給 l
        check(num,l)       # 遞歸
    else:
        print("OK!")

check(8900,nums)  # OK!
相關文章
相關標籤/搜索