給定乙個整數 n,求以 1 … n 為節點組成的二叉搜尋樹有多少種?
輸入:
3輸出:
5解釋:
給定 n =
3, 一共有 5 種不同結構的二叉搜尋樹:13
321 \ /
// \ \
321132/
/ \ \
2123
這題我想用95題的思路,構建出來,然後統計最外層的樹的個數。(時間複雜度太高了) 不出意外收穫了lte.
總感覺有什麼不對,感覺有什麼規律。對於95題,我們是把每個結點都當做根結點,在它左邊的結點當做它的左子樹的根,在它右邊的結點當做它的右子樹的根。
這樣的話,其實對於固定長度的序列來說,生成的樹的數目都是一樣的。
也就是說:如果乙個序列的長度為3,別管序列中儲存的值是什麼,那麼他們生成的二叉搜尋樹的數量是確定的。
可見,問題可以分解成規模較小的子問題。因此,我們可以儲存並復用子問題的解。為啥?以序列長度為3為例:
這個序列可生成的樹數為:
以第乙個位置的元素為根,以第二個位置的元素為根,以第三個元素為根。 所有的數加起來。
而以第乙個位置的元素為根,則右邊兩個數是它的右子樹。 右子樹長度為2,它的可生成的樹數為: 以第乙個位置的元素為根,以第二個位置的元素為根。加起來。
而這個第乙個位置元素為根,第二個元素為右子樹的情況,只有一種。
第二個位置為根,第乙個元素為左子樹的情況,只有一種。
所以我們得到長度為2的序列的樹數為2,儲存下來。直接給上層使用。
我們用res陣列來儲存,res[i]為長度為i的序列的二叉搜尋樹的個數。
總結一下就是,為了以 3 為根從序列 [1, 2, 3, 4, 5, 6, 7] 構建二叉搜尋樹,我們需要從左子串行 [1, 2] 構建左子樹,從右子串行 [4, 5, 6, 7] 構建右子樹,然後將它們組合(即笛卡爾積)。而左子串行[1,2]構建的左子樹的二叉搜尋樹個數等於res[2], [4, 5, 6, 7] 對應res[4]。乘起來即可。為啥呢?左子樹有這麼多種,右子樹有這麼多種,任意組合就是個樹。 所以是笛卡爾積(左邊集合中的所有值分別於右邊集合中的所有值都相乘一遍)。
(方法一)
方法一在數學裡叫做卡特蘭數。我們可以直接用公式來做。
根據這兩個公式,我們可以推出來。(方法二)
public
intnumtrees1
(int n)
}return res[n]
;}
public
intnumtrees
(int n)
return
(int
)res;
}
96 不同的二叉搜尋樹
給定乙個整數 n,求以 1 n 為節點組成的二叉搜尋樹有多少種?示例 輸入 3 輸出 5 解釋 給定 n 3,一共有 5 種不同結構的二叉搜尋樹 1 3 3 2 1 3 2 1 1 3 2 2 1 2 3思路 這個題目實際上是乙個數學題,設整數p組成的二叉樹共有c p 種情況。當給定乙個整數n的時候...
96 不同的二叉搜尋樹
二叉搜尋樹,又被稱為是二叉查詢樹 二叉排序樹,這種樹其左子樹所有節點的值均小於根節點的值,其右子樹所有節點的值均大於根節點的值,並且其左 右子樹均為二叉搜尋樹。空樹也是二叉搜尋樹。方法一 動態規劃法 這道題可以用動態規劃的思想去解決。由於給定的節點值為1 n,是一組從小到大順序排列的資料,其中,任意...
96 不同的二叉搜尋樹
dp i 代表有 i 個結點 1.i 時候的二叉搜尋樹種數。首先就是要考慮怎麼和之前的dp連線起來,也就是說選擇有幾種。首先可以就直接把 i 這個數放在 i 1 二叉樹的根節點,二叉搜尋樹的種數就是dp i 1 如果把 i 放在左子樹,i 1是根節點,那就有dp 1 dp i 2 左子樹 右子樹 在...