zoukankan      html  css  js  c++  java
  • 代码题(41)— 不同的二叉搜索树

    1、96. 不同的二叉搜索树

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

    示例:

    输入: 3
    输出: 5
    解释:
    给定 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) {
            vector<int> dp(n+1,0);
            dp[0] = 1;
            dp[1] = 1;
            
            for(int i=2;i<=n;++i)
            {
                for(int j=0;j<i;++j)
                {
                    dp[i] += dp[j]*dp[i-j-1];//原来的值加上 左子树个数*右子树个数
                }
            }
            return dp[n];
        }
    };

    2、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

    之前那个只要求算出所有不同的二叉搜索树的个数,这道题让把那些二叉树都建立出来。这种建树问题一般来说都是用递归来解,这道题也不例外,划分左右子树,递归构造。

      需要建立树,只是把代码粘过来了。

    class Solution {
    public:
        vector<TreeNode *> generateTrees(int n) {
            if (n == 0) return {};
            return *generateTreesDFS(1, n);
        }
        vector<TreeNode*> *generateTreesDFS(int start, int end) {
            vector<TreeNode*> *subTree = new vector<TreeNode*>();
            if (start > end) subTree->push_back(NULL);
            else {
                for (int i = start; i <= end; ++i) {
                    vector<TreeNode*> *leftSubTree = generateTreesDFS(start, i - 1);
                    vector<TreeNode*> *rightSubTree = generateTreesDFS(i + 1, end);
                    for (int j = 0; j < leftSubTree->size(); ++j) {
                        for (int k = 0; k < rightSubTree->size(); ++k) {
                            TreeNode *node = new TreeNode(i);
                            node->left = (*leftSubTree)[j];
                            node->right = (*rightSubTree)[k];
                            subTree->push_back(node);
                        }
                    }
                }
            }
            return subTree;
        }
    };
  • 相关阅读:
    Emmet使用
    正则参考网址
    sublime通用快捷键 汉化 安装 插件
    【真正福利】成为专业程序员路上用到的各种优秀资料、神器及框架
    生产事故的优化经历
    Windows下oracle打补丁步骤
    Oracle10g完全卸载正确步骤
    在windows2003系统上安装两个版本的oracle
    oracle11g数据库升级数据库升级
    oracle Imp和exp以及导入常见的错误
  • 原文地址:https://www.cnblogs.com/eilearn/p/9447604.html
Copyright © 2011-2022 走看看