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

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

题目描述

给定一个整数 n,生成所有由 1 … n 为节点所组成的 二叉搜索树 。
在这里插入图片描述

解题

    对一个二叉搜索树的中序遍历结果就是得到一个有序的序列 { 1 , 2 , 3... n } \{1, 2, 3...n\} {1,2,3...n},本题的目的是要求所有能得到这个有序序列的二叉搜索树。观察这个有序序列,每一个数字都可以作为根节点,它将整个序列一分为二,左边一部分,右边一部分,左边的数字在二叉树上对应其左子树部分,右边的数字对应其右子树部分,这样根节点、左右子树大致划分完成。同样地,对左右子树也可以有类似的划分,即左边的每一个数字都可以作为左子树的根节点,同样能将左子树划分为左右两部分,这样把整个复杂的问题分解成具有相似处理方式的子问题,就可以借助循环或迭代完成了。这里可以想到,应该是先解决子树的问题,然后回到父节点,再解决更高一层的树的问题,因此使用递归更合适。
    整个问题是将序列 { 1 , 2 , 3... n } \{1, 2, 3...n\} {1,2,3...n}转化为二叉搜索树,子问题是将某一段子序列转化为二叉搜索树的子树,因此应当设计这样一个递归函数,它接收两个参数,指定数字范围,即子序列,返回这个子序列能够组成的所有二叉搜索(子)树,返回结果可以以数组的形式,在当前迭代过程中,如果参数表示的数字范围是有效的,当前数字范围的每一个数字 m m m的左右部分 [ 1 , m − 1 ] [1,m-1] [1,m1]和[m+1,n]调用迭代函数的返回结果表示所有的左右子树,以此建立所有子树的集合并返回这个集合。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
private:
    vector<TreeNode *> generateTrees(int l, int r){
        if (l > r) return {NULL};
        vector<TreeNode *> cur_nodes;
        for (int n=l; n <= r; ++n){
            vector<TreeNode *> left_nodes(std::move(generateTrees(l, n-1)));  //所有左子树集合
            vector<TreeNode *> right_nodes(std::move(generateTrees(n+1, r)));  //所有右子树集合
            TreeNode *cur_node;
            //建立所有当前子树的集合
            for (int i=0; i<left_nodes.size(); ++i){
                for (int j=0; j<right_nodes.size(); ++j){
                    cur_node = new TreeNode(n);
                    cur_node->left = left_nodes[i];
                    cur_node->right = right_nodes[j];
                    cur_nodes.emplace_back(cur_node);
                }
            }
        }
        return cur_nodes;
    }
public:
    vector<TreeNode*> generateTrees(int n) {
        if (n==0) return vector<TreeNode*>();
        vector<TreeNode *>out(std::move(generateTrees(1, n)));
        return out;
    }
};

    上面方法实现过程中有一个小小的缺陷,那就是同样一个子序列可能会计算多次,因此可以借助记忆化的方式,把子序列的结果保存,当需要时直接返回保存的结果,不需要再计算一次,这里实际上就是保存所有子序列所能转化的子树。

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
private:
    vector<vector<vector<TreeNode*>>> nodes;
    vector<TreeNode*>generateTrees(int l, int r){
        if (l > r) return vector<TreeNode*>{NULL};
        if (!nodes[l][r].empty()) return nodes[l][r];
        vector<TreeNode *> cur_node_vect;
        for (int n=l; n<=r; ++n){
            vector<TreeNode*> l_nodes = generateTrees(l, n-1);
            vector<TreeNode*> r_nodes = generateTrees(n+1, r);
            for (auto i : l_nodes){
                for (auto j:r_nodes){
                    TreeNode *cur_node = new TreeNode(n);
                    cur_node->left = i;
                    cur_node->right = j;
                    cur_node_vect.emplace_back(cur_node);
                }
            }
        }
        return cur_node_vect;
    }
public:
    vector<TreeNode*> generateTrees(int n) {
        if (n==0) return vector<TreeNode *>();
        nodes.resize(n+1, vector<vector<TreeNode*>>(n+1));
        return generateTrees(1, n);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值