1. 程式人生 > >LeetCode96不同的二叉查詢樹

LeetCode96不同的二叉查詢樹

題目:

給出 n,問由 1...n 為節點組成的不同的二叉查詢樹有多少種?

例如,
給出 n = 3,則有 5 種不同形態的二叉查詢樹:

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

分析:

動態規劃問題,自己看了題目之後感覺無從下手,還是去看了網上的解題報告。。。。。

大概是這個意思:

  1. 給出的n代表有n個節點,1,2,3,4,5,……n,這些節點組成的不同形態的二叉查詢樹,是說中序遍歷這些樹,得到的序列就是 1,2,3,4,5,……n。
  2. 根據二叉查詢樹可以知道,某根節點x,它的左子樹的值全<=x(當然本題不存在等於的情況),它的右子樹的值全>=x,所以,當它的根節點是 1 的時候,左子樹個數為 0 ,右子樹的個數為 n-1, 當它的根節點為 2 的時候, 左子樹個數為 1, 右子樹的個數為 n-2……
  3. 還有一個規律,就是這棵樹的不同形態的二叉查詢樹的個數,就是根節點的  左子樹的個數*右子樹的個數,想想還是很容易理解的,就是左邊的所有情況乘以右邊的所有情況,知道這個規律就好做啦。
  4. 動態規劃,從前到後計算出當有i個節點時,它有多少種不同形態的樹。nums[i] += nums[j] * nums[i-1-j]  (初始j==0,每做完一步j++)。(這裡i-1-j 減掉的 1 代表是根節點佔了一個位置)

當節點個數為0時有一種形態的樹(也就是空樹吧),當節點個數為1時有一種形態的樹,之後就可以向下繼續計算節點為2,3,4,5,……n。

程式碼:

class Solution {
    public int numTrees(int n) {
        if (n == 0)return 0;
        if (n == 1) return 1;

        int[] nums = new int[n+1];
        nums[0] = 1; nums[1] = 1;

        for (int i = 2; i <= n; i++) {
            for (int j = 0; j < i; j++) {
                nums[i] = nums[i] + nums[j] * nums[i-1-j];
            }
        }
        return nums[n];

    }
}