給定二叉樹的節點個數來計算能夠構成多少種不同的二叉樹。
採用的是遞迴的思想來解決這類問題。
1、因為採用遞迴的思想,我們的結束條件就是當節點個數為0.此時節點個數為0的情況,這時候構成的樹的情況為空樹,即二叉樹的個數是1.
2、因為是二叉樹,我們只需要分為兩邊來計算。即滿足這樣的條件,從根節點下來,能夠成左邊的情況的個數乘以右邊的個數的情況想乘,就得到此時這種情況的個數。例如:總共有3個節點,左邊分配2個(能構成的情況為2),右邊分配1個節點(能構成的情況為1),即本次分配的情況總數為2*1=2
3、實際上節點數為1的時候,構成的情況也是1,和0是一樣的,所以遞迴的條件,就是當節點數為0就結束。所以每次的結果都會遞迴到0。
**實現:
'''
計算二叉樹的個數
'''def count(n):
# root : 1
# left : k [0,n-1]
# right : n - 1 - k
if n == 0:
return 1
sum = 0
for k in range(n):
sum += count(k) * count(n-1-k)
return sum
用一張圖來表示呼叫棧的變化以及程式的執行過程。我們以n=3為例,其他的(n更大)的情況都是一樣的計算。
上圖,詳細解釋了每一步的執行過程。上述呼叫棧的過程遵從左到右、從上到下的過程。執行過程遵從,從右到做、從下到上的順序。
在上述的**中,有乙個很大的缺點,在呼叫棧中就體現得很明確,當我們第一步執行count(0)和count(2)後,發現後面還會用到這些,會被重複的在呼叫棧中執行,在時間和空間上都是很大的浪費。
解決方法,我們可以建立乙個快取機制,使得每次執行過的count()被儲存在快取中,這樣的話,當我們下次執行到ciunt()時,如果已經在快取中,就直接從快取中取(時間複雜度為o(1)),如果不存在我們才會遞迴。
其**如下:
'''
新增快取的方式來實現時間複雜度下降
'''def count_tree(n):
# root : 1
# left : k [0,n-1]
# right : n - 1 - k
sum = count_tree.cache.get(n,0)
if sum:
return sum
for k in range(n):
sum += count_tree(k) * count_tree(n-1-k)
return sum
count_tree.cache =
計算二叉樹的結點個數
include using namespace std extern int gnum 0 struct infor class test static int creattrees struct infor p,int k if 2 k creattrees q,1 creattrees q,2 ...
二叉樹計算
術語 1.節點的度 乙個節點含有的子樹的個數稱為該節點的度 2.葉節點或終端節點 度為零的節點 3.非終端節點或分支節點 度不為零的節點 4.父親節點或父節點 若乙個節點含有子節點,則這個節點稱為其子節點的父節點 5.兄弟節點 具有相同父節點的節點互稱為兄弟節點 6.節點的層次 從根開始定義起,根為...
二叉樹組合個數
hw 2020.8.19筆試第二題 題目描述 給出二叉樹上每個節點的深度,請你計算滿足條件的二叉樹共有多少種。輸入描述 第一行包含乙個整數n,表示二叉樹上節點的數量 1 n 1000 第二行包含n個整數,d1,d2,dn,表示每個節點的深度 0 di n 1 輸出描述 輸出滿足條件的二叉樹數量,因為...