01 动态规划 之 不同的二叉搜索树(LeetCode 96)

一、问题描述

原题官网

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

2、描述给出先序遍历(根左右) 和 中序遍历(左根右)和 后序遍历(左右根)

输入3 输出 5

先序遍历:(1 3 2)、 (3 2 1)、(3 1 2)、(2 1 3)、(1 2 3)

中序遍历: (1 2 3)、(1 2 3)、(2 1 3)、(1 2 3)、(1 3 2)

3、 解决思路

1) 对应给定一个有序序列 1⋯n,为了构建出一棵二叉搜索树。遍历每个数字i,将1-()序列
作为左子树,将(i+1)-n 序列作为右子树

4、定义两个函数

1)G(n): 长度为 n 的序列能构成的不同二叉搜索树的个数。

  1. F(i,n): 以 i 为根、序列长度为 n 的不同二叉搜索树个数(n>=i >=1)

二、解决代码

卡塔兰数(catalan)

1、方法一 (动态规划)

2、方法二(数学之卡塔兰数)

三代码

package com.hao.algorithm;

/**
 * @author haoxiansheng
 * 算法描述:、给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种?
 */
public class DynamicProgrammingDemo1 {
    public static void main(String[] args) {
        System.out.println(numTress(3));
        System.out.println(numTressTwo(3));
    }

    /**
     * 1、动态规划 求解
     * 时间复杂度O(n^2): n表示二叉搜索树的节点个数,G(n)函数一共有n个值需要求解,每次求解需要O(n)的时间复杂度
     * 空间复杂度O(n): 需要O(n)的空间存储 G 数组
     *
     *
     * @param n
     * @return
     */
    public static int numTress(int n) {
        int[] G = new int[n + 1];
        G[0] = 1;
        G[1] = 1;
        for (int i = 2; i <= n; i++) {
            for (int j = 1; j <= i; j++) {
                G[i] += G[j - 1] * G[i - j];
            }
        }
        return G[n];
    }

    /**
     * 2、数学 方法求解 卡塔兰数
     *
     * 空间复杂度 O(1) 只需要常数空间存放若干变量。
     * 时间复杂度 O(n) n表示二叉搜索树的节点个数,只需要循环遍历一次即可。
     *
     * @param n
     * @return
     */
    public static int numTressTwo(int n) {
        // 需要用long 防止计算溢出
        long C = 1;
        for (int i = 0; i < n; ++i) {
            C = C * 2 *(2 * i + 1) / (i + 2);
        }
        return (int) C;
    }
}


你可能感兴趣的:(力扣)