LeetCode 96——不同的二叉搜索树

1. 题目

2. 解答

以 \(1, 2, \cdots, n\) 构建二叉搜索树,其中,任意数字都可以作为根节点来构建二叉搜索树。当我们将某一个数字作为根节点后,其左边数据将构建为左子树,右边数据将构建为右子树。因此,这是一个递归问题。

若以第 \(i\) 个数据为根节点,其左边数据有 \(i-1\) 个,左子树可能情况为 left_num,右边数据有 \(n-i\) 个,右子树可能情况为 right_num,因此以当前数据为根节点可以构建出 left_num * right_num 个二叉搜索树。

所以,我们要做的就是遍历 \(i = 1\cdots n\),统计出每个数据作为根节点可以构建出的二叉搜索树总个数即可。

  • 递归法
class Solution {
public:

       int numTrees(int n) {

        int sum = 0;

        if (n <= 1) return 1;

        // 以当前的数为根节点,左右两边的数分别构建子树
        for (int i = 1; i <= n; i++)
        {
            int left_num = numTrees(i - 1); // 左边的数可以构建多少个二叉搜索树

            int right_num = numTrees(n - i); // 右边的数可以构建多少个二叉搜索树

            sum += left_num * right_num;
        }

        return sum;
    }
};

但是上面的程序运行时超时了,其实我们只需要统计一半数据就可以了,因为两边是对称的。

比如我们有 1,2,3,4,5 五个数,以 2 作为根节点,左边有 1 个数,右边有 3 个数。以 4 作为根节点,左边有 3 个数,右边有 1 个数。这两种情况是一样的,因此如果数据个数为偶数,我们只需要统计一半数据即可,而为奇数的话我们就要再多统计一个中间数据。

class Solution {
public:

    int numTrees(int n) {

        int sum = 0;

        if (n <= 1) return 1;

        int is_odd = n % 2;
        int mid = n / 2;

        // 以当前的数为根节点,左右两边的数分别构建子树
        for (int i = 1; i <= mid; i++)
        {
            int left_num = numTrees(i - 1); // 左边的数可以构建多少个二叉搜索树

            int right_num = numTrees(n - i); // 右边的数可以构建多少个二叉搜索树

            sum += left_num * right_num;
        }

        sum = sum * 2;

        if (is_odd) sum = sum + numTrees(mid) * numTrees(n - mid - 1);

        return sum;
    }
};

此外,我们还可以定义一个全局变量,来存放已经计算过的数值,避免在递归过程中大量地重复计算。

class Solution {
public:

    #define MAX 1000

    int nums[MAX]; // 存放已经计算过的数值

    int numTrees(int n) {

        int sum = 0;

        //if (n <= 0) return 1;
        if (n <= 1) return 1;

        // 以当前的数为根节点,左右两边的数分别构建子树
        for (int i = 1; i <= n; i++)
        {
            if (nums[i-1] == 0) nums[i-1] = numTrees(i - 1); // 左边的数可以构建多少个二叉搜索树
            int left_num = nums[i-1];

            if (nums[n-i] == 0) nums[n-i] = numTrees(n - i); // 右边的数可以构建多少个二叉搜索树
            int right_num = nums[n-i]; 

            sum += left_num * right_num;
        }

        return sum;
    }
};
  • 迭代法

    还可以将递归改写为循环,避免函数多次调用执行效率较低。

class Solution {
public:

    int numTrees(int n) {

        int nums[n+1] = {0};

        nums[0] = 1;
        nums[1] = 1;

        if (n <= 1) return 1;

        for (int i = 2; i <= n; i++)
        {
            // 从 n=2 开始统计可以构建多少个不同的二叉搜索树
            for (int j = 1; j <= i; j++)
            {
                nums[i] += nums[j-1] * nums[i-j];
            }
        }

        return nums[n];
    }
};      

获取更多精彩,请关注「seniusen」!

原文地址:https://www.cnblogs.com/seniusen/p/9991185.html

时间: 2024-10-01 02:45:17

LeetCode 96——不同的二叉搜索树的相关文章

Leetcode 96. 不同的二叉搜索树

题目链接 https://leetcode.com/problems/unique-binary-search-trees/description/ 题目描述 给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种? 示例: 输入: 3 输出: 5 解释: 给定 n = 3, 一共有 5 种不同结构的二叉搜索树: 1 3 3 2 1 \ / / / \ 3 2 1 1 3 2 / / \ 2 1 2 3 题解 首先定义一个函数G[n]:表示1...n构成的二叉搜索树的个数.1..

LeetCode.938-范围内求二叉搜索树节点值之和(Range Sum of BST)

这是悦乐书的第359次更新,第386篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第221题(顺位题号是938).给定二叉搜索树的根节点,返回节点值在[L,R]之间的所有节点的值的总和.二叉搜索树的节点值唯一.例如: 输入:root = [10,5,15,3,7,null,18],L = 7,R = 15 输出:32 输入:root = [10,5,15,3,7,13,18,1,null,6],L = 6,R = 10 输出:23 注意: 树中的节点数最多为1000

96. 不同的二叉搜索树

给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种? 示例: 输入: 3输出: 5解释:给定 n = 3, 一共有 5 种不同结构的二叉搜索树: 1 3 3 2 1 \ / / / \ \ 3 2 1 1 3 2 / / \ \ 2 1 2 3 来源:力扣(LeetCode)链接:https://leetcode-cn.com/problems/unique-binary-search-trees著作权归领扣网络所有.商业转载请联系官方授权,非商业转载请注明出处. 直接用公式

LeetCode动画 | 1038. 从二叉搜索树到更大和树

今天分享一个LeetCode题,题号是1038,标题是:从二分搜索树到更大和数. 题目描述 给出二叉搜索树的根节点,该二叉树的节点值各不相同,修改二叉树,使每个节点 node 的新值等于原树中大于或等于 node.val 的值之和. 提醒一下,二叉搜索树满足下列约束条件: 1)节点的左子树仅包含键小于节点键的节点. 2)节点的右子树仅包含键大于节点键的节点. 3)左右子树也必须是二叉搜索树. 示例: 输入:[4, 1, 6, 0, 2, 5, 7, null, null, null, 3, nu

Leetcode 95.不同的二叉搜索树II

给定一个整数 n,生成所有由 1 ... n 为节点所组成的二叉搜索树. 示例: 输入: 3 输出: [   [1,null,3,2],   [3,2,null,1],   [3,1,null,null,2],   [2,1,3],   [1,null,2,null,3] ] 解释: 以上的输出对应以下 5 种不同结构的二叉搜索树: 1 3 3 2 1 \ / / / \ 3 2 1 1 3 2 / / \ 2 1 2 3 1 /** 2 * Definition for a binary tr

[LeetCode] Split BST 分割二叉搜索树

Given a Binary Search Tree (BST) with root node root, and a target value V, split the tree into two subtrees where one subtree has nodes that are all smaller or equal to the target value, while the other subtree has all nodes that are greater than th

二叉树-二叉搜索树(中序)

题型: (1)验证 (2)修复(排列不正确,修复) (3)构造(给排列求树-平衡的:种类) (4)利用性质求第n个结点 二叉搜索树的思路:中序输出+相关操作 如果要求空间复杂度O(1),考虑莫里斯遍历 98. 验证二叉搜索树    面试题 04.05. 合法二叉搜索树 (1) 思路:中序排列,看次序 1 class Solution { 2 public boolean isValidBST(TreeNode root) { 3 // if(root==null){ // 题目空树是true 4

LeetCode(96): 不同的二叉搜索树

Medium! 题目描述: 给定一个整数 n,求以 1 ... n 为节点组成的二叉搜索树有多少种? 示例: 输入: 3 输出: 5 解释: 给定 n = 3, 一共有 5 种不同结构的二叉搜索树: 1 3 3 2 1 \ / / / \ 3 2 1 1 3 2 / / \ 2 1 2 3 解题思路: 这道题实际上是Catalan Number卡塔兰数的一个例子,如果对卡塔兰数不熟悉的童鞋可能真不太好做.先来看当 n = 1的情况,只能形成唯一的一棵二叉搜索树,n分别为1,2,3的情况如下所示:

LeetCode 501. Find Mode in Binary Search Tree (找到二叉搜索树的众数)

Given a binary search tree (BST) with duplicates, find all the mode(s) (the most frequently occurred element) in the given BST. Assume a BST is defined as follows: The left subtree of a node contains only nodes with keys less than or equal to the nod