1. 程式人生 > >二叉樹系列---求包含n個節點的二叉查詢樹的種類數

二叉樹系列---求包含n個節點的二叉查詢樹的種類數

題目1

求包含n個節點的二叉查詢樹的種類數;

方法1

設dp[i]表示共有i個節點時,能產生的BST樹的個數
n == 0 時,空樹的個數必然為1,因此dp[0] = 1
n == 1 時,只有1這個根節點,數量也為1,因此dp[1] = 1
當根節點元素為 1, 2, 3, 4, 5, …, i, …, n時,基於以下原則的BST樹具有唯一性:
以i為根節點時,其左子樹構成為[0,…,i-1],其右子樹構成為[i+1,…,n]構成
因此,dp[i] = sigma(dp[0…k] * dp[k+1…i]) 0 <= k < i - 1

public int numTrees(int n) {
        if(n==0||n==1){
            return 1;
        }
        int[] nums=new int[n+1];
        nums[0]=1;
        nums[1]=1;

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

方法2

選擇一個節點,它的左右子樹個數的乘積就是總的個數,可以遞迴解決

public int numTrees2(int n) {
        if(n<1){
            return 1;
        }
        int sum=0;
        for(int i=1;i<=n;i++){
            sum+=numTrees2(i-1)*numTrees2(n-i);
        }
        return sum;
    }

題目2

求包含n個節點(從1到n,n個節點)的所有二叉查詢樹;(不是求個數,而是求所有二叉查詢樹);

思路

/*
* 每次選取一個結點為根(從1到n依次作為根),然後遞迴求解左右子樹的所有結果,
* 最後根據左右子樹的返回的所有子樹,依次選取
* 然後接上(每個左邊的子樹跟所有右邊的子樹匹配,
* 而每個右邊的子樹也要跟所有的左邊子樹匹配,總共有左右子樹數量的乘積種情況),
* 構造好之後作為當前樹的結果返回
*/

實現

public ArrayList<TreeNode> generateTrees(int n) {
        return createTrees(1,n);
    }
/*
     * 每次選取一個結點為根(從1到n依次作為根),然後遞迴求解左右子樹的所有結果,
     * 最後根據左右子樹的返回的所有子樹,依次選取
     * 然後接上(每個左邊的子樹跟所有右邊的子樹匹配,
     *       而每個右邊的子樹也要跟所有的左邊子樹匹配,總共有左右子樹數量的乘積種情況),
     * 構造好之後作為當前樹的結果返回
     */
    private ArrayList<TreeNode> createTrees(int start, int end) {
        ArrayList<TreeNode> res=new ArrayList<TreeNode>();
        if(start>end){
            res.add(null);
            return res;
        }
        for(int i=start;i<=end;i++){//i作為根
            ArrayList<TreeNode> leftList=createTrees(start,i-1);
            ArrayList<TreeNode> rightList=createTrees(i+1,end);

            /*每個左邊的子樹跟所有右邊的子樹匹配,而每個右邊的子樹也要跟所有的左邊子樹匹配;
             * 總共有左右子樹數量的乘積種情況
             */
            for(TreeNode left:leftList){
                for(TreeNode right:rightList){
                    TreeNode root=new TreeNode(i); //i作為根
                    root.left=left;
                    root.right=right;
                    res.add(root);
                }
            }
        }
        return res;
    }