二叉搜索树

124 阅读2分钟

题目

给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种?

示例:

输入: 3 输出: 5

动态规划

public class Main {


    public static void main(String[] args) {

        Main main = new Main();
        main.numTrees(4);

    }

    public int numTrees(int n) {
        int [] dpTable = new int[n];

        for (int i = 0; i < n; i ++) {
            if (i == 0) {
                dpTable[i] = 1;
            }
            if (i == 1) {
                dpTable[i] = 2;
            }
            if (i >= 2) {
                for (int j = 0; j <= i; j ++) {
                    // 当j为二叉树的root时
                    // j - 0 代表j左边的二叉树节点
                    // i - j 代表j右边的二叉树节点
                    int jLeft = 0;
                    if (j > 0) {
                        jLeft = dpTable[j - 1];
                    }
                    int jRight = 0;
                    if (j < i) {
                        jRight = dpTable[i - j - 1];
                    }
                    if (jLeft == 0 || jRight == 0) {
                        dpTable[i] = dpTable[i] + jLeft + jRight;
                    } else {
                        dpTable[i] = dpTable[i] + jLeft * jRight;
                    }

                }

            }

        }

        return dpTable[n - 1];

    }

}

基本思路

  1. 首先明确搜索二叉树(注意不是完全二叉树)的定义, 即一棵二叉树中, 左节点的值 < 根节点的值 < 右节点的值.

  2. 输入为1...n, 是按顺序有规律的

  3. 然后发现当1到n中每个值如果分别作为总二叉树的根的时候, 例如当n = 4, 3为root, 那么1, 2 一定在3的左边, 4在3的右边. 即通过轮换不同的数字作为root, 可以分成两个子二叉树, 即两个子问题, 因此可以用动态规划来解决

  4. 也就是dp[i]代表当n为i的时候, 一共有多少种构成, 那么当i作为root节点, i之间的数字全部作为左子数, 那么左子数有多少种可能呢, 那就将左边子树从头遍历一遍, 每个节点作为左子树的root, 然后看当前root的左右一共有几种可能(已经计算过的)

  5. 采用dptable来记录子问题的答案

  6. 需要注意在计算某个root左右两边的节点数量和索引关系, 不要被绕晕了