1. 程式人生 > >leetcode 96. 不同的二叉搜尋樹

leetcode 96. 不同的二叉搜尋樹

給定一個整數 n,求以 1 … n 為節點組成的二叉搜尋樹有多少種?

示例:

輸入: 3
輸出: 5
解釋:
給定 n = 3, 一共有 5 種不同結構的二叉搜尋樹:

   1         3     3      2      1
    \       /     /      / \      \
     3     2     1      1   3      2
    /     /       \                 \
   2     1         2                 3

這裡解題思路是:假設,現在有n個數,那麼,理論上講,每個數字都可以作為這個樹的樹根。

解釋一下上面那些樹產生的過程:

  1. n=0 表示,有0個點,那麼,可以組成的二叉查詢樹就一個,那就是空樹
  2. n=1表示,有1個點,那麼,可以組成的二叉查詢樹就一個,那就是根節點為1,左右子樹均為空子樹
  3. n=2表示,有2個點,那麼,可以組成的二叉查詢數就兩個,假設,點集合為[0,1,2](這裡的第一個0表示空點,就是空子樹)那麼,0不能做根,如果1做根,那麼左子樹為0,右子樹就是2(看出來了嗎剛好是從1處截斷了),如果2做根,那麼左子樹為[0,1],右子樹為空子樹(剛好從2處截斷了(遞推為f(3)=f(0)(2)+f(1)f(1)+f(2)f(0)))。
  4. 以此類推,假設n=t,那麼表示,有t個點,那麼假設讓第x個點做根,那麼,左子樹為[0,……,t-1],右子樹為[t+1,……,n],那麼,最終的答案是 f(t) * f(n-t-1)這裡f(a)表示如果有a個點,那麼可以組成的樹的個數(畢竟我們是在處理這些數字之前,他們就有順序了,比如,[0,1,2]
class Solution {
public:
    int numTrees(int n) {
        vector<int> vi;
        if (n==0) return 1;
        if (n==1) return 1;
        vi.push_back(1);
        vi.push_back(1);
        for (int i = 2; i <= n; ++i) {
            //這裡計算 n=i的情況
            int tmp=0;
            for (int j = 0
; j < i; ++j) { tmp += vi[j]*vi[i-j-1]; } vi.push_back(tmp); } return vi.back(); } };