[2021 Spring] CS61A 學習筆記 lecture 7 tree recursion
阿新 • • 發佈:2021-06-16
lecture7 主要講樹遞迴、線性遞迴、尾遞迴。
課本:http://composingprograms.com/pages/17-recursive-functions.html
- 遞迴分類
- 問題 find_zero
- Finding a Path
- Counting the Paths
- Another Recursion Problem: Counting Partitions
- Recurrences
遞迴分類
樹遞迴:每次呼叫會多次呼叫自身
線性遞迴:每次呼叫最多進行一次遞迴呼叫
尾遞迴:每次呼叫最多進行一次遞迴呼叫,且只執行自身呼叫(沒有其他變數)
關於尾遞迴的說明,參考StackOverflow上的What is tail recursion。
問題 find_zero
尾遞迴1
尾遞迴2
線性遞迴
樹遞迴
可以呼叫多次,但是不是必須的
Finding a Path
Path-Finding Program
每一步都要向下移動一格,向左右移動不超過一格。
is_path Solution
def is_path(blocked, x0, y0): """True iff there is a path of squares from (X0, Y0) to some square (x1, 0) such that all squares on the path (including first and last) are unoccupied. BLOCKED is a predicate such that BLOCKED(x, y) is true iff the grid square at (x, y) is occupied or off the edge. Each step of a path goes down one row and 1 or 0 columns left or right.""" if blocked(x0, y0): return False elif y0 == 0: return True else: return (is_path(blocked, x0-1, y0-1) or is_path(blocked, x0, y0-1) or is_path(blocked, x0+1, y0-1))
Counting the Paths
num_paths Solution
def num_paths(blocked, x0, y0): """Return the number of unoccupied paths that run from (X0, Y0) to some square (x1, 0). BLOCKED is a predicate such that BLOCKED(x, y) is true iff the grid square at (x, y) is occupied or off the edge. """ if blocked(x0, y0): return 0 elif y0 == 0: return 1 else: return num_paths(blocked, x0, y0-1) \ + num_paths(blocked, x0-1, y0-1) \ + num_paths(blocked, x0+1, y0-1) # OR (looking ahead a bit) # return sum( (num_paths(blocked, x0+k, y0-1) # for k in range(-1, 2)) # )
A Change in Problem
change:不限制移動時必須向下移動一格,會導致無限遞迴
And a Little Analysis
is_path每次呼叫會呼叫三次自身,初始y位置為y0,可能的呼叫次數就可能達到3**y0,指數式增長。
Another Recursion Problem: Counting Partitions
Identifying the Problem in the Problem
Counting Partitions: Code
兩種情況:選擇k和不選擇k
def num_partitions(n, k):
"""Return number of distinct ways to express N as a sum of
positive integers each of which is <= K, where K > 0."""
if n < 0:
return 0
elif k == 1:
return 1
else:
return num_partitions(n-k, k) + num_partitions(n, k-1)
Recurrences
斐波那契遞迴,複雜度很高,簡化方法後面會講到。