leetcode 95. Unique Binary Search Trees II 递归构造所有可能的搜索二叉树BST + 卡特兰数

Given an integer n, generate all structurally unique BST’s (binary search trees) that store values 1…n.

For example,
Given n = 3, your program should return all 5 unique BST’s shown below.

1 3 3 2 1
\ / / / \ \
3 2 1 1 3 2
/ / \ \
2 1 2 3

这道题就是穷举所有可能的搜索二叉树BST的数量。就是求解卡特兰数。也可以参考这个题 leetcode 96. Unique Binary Search Trees 卡特兰数

说实话,这种递归我写不出来,我是参考网上的教程做得,但是看到代码就自动应该是这么做得。

建议和leetcode 87. Scramble String 字符串拼凑 && DFS深度优先搜索 一起学习,因为我感觉递归思路相似

这道题的做法感觉和leetcode 105. Construct Binary Tree from Preorder and Inorder Traversal 中前序构造BSTleetcode 106. Construct Binary Tree from Inorder and Postorder Traversal 中后序构造BST 一起学习,因为做法类似

这道题可以和leetcode 108. Convert Sorted Array to Binary Search Tree 构建平衡二叉搜索树 + DFS 一起学习

同时和这一道题leetcode 241. Different Ways to Add Parentheses 深度优先遍历DFS + 类似构造所有的二叉搜索树 很像,值得一起学习

还有这一道题leetcode 282. Expression Add Operators 任意添加运算符计算结果 +深度优先遍历DFS

这道题很值得学习。

代码如下:

import java.util.ArrayList;

/*class TreeNode
{
     int val;
     TreeNode left;
     TreeNode right;
     TreeNode(int x) { val = x; }
}*/

public class Solution
{
    /*
     * http://blog.csdn.net/linhuanmars/article/details/24761437
     * 
     * 这道题是求解所有可行的二叉查找树,从Unique Binary Search Trees中我们已经知道,
     * 可行的二叉查找树的数量是相应的卡特兰数,不是一个多项式时间的数量级,所以我们要求
     * 解所有的树,自然是不能多项式时间内完成的了。算法上还是用求解NP问题的方法来求解,
     * 也就是N-Queens中介绍的在循环中调用递归函数求解子问题。思路是每次一次选取一个结点为根,
     * 然后递归求解左右子树的所有结果,最后根据左右子树的返回的所有子树,依次选取然后接上
     * (每个左边的子树跟所有右边的子树匹配,而每个右边的子树也要跟所有的左边子树匹配,总共
     * 有左右子树数量的乘积种情况),构造好之后作为当前树的结果返回。代码如下
     * */
    public ArrayList<TreeNode> generateTrees(int n) 
    {
        if(n<=0)
            return new ArrayList<TreeNode>();
        else
            return byRecursion(1,n);
    }

    private ArrayList<TreeNode> byRecursion(int left, int right) 
    {
        ArrayList<TreeNode> res=new ArrayList<>();
        if(left>right)
            res.add(null);
        else 
        {
            for(int i=left;i<=right;i++)
            {
                ArrayList<TreeNode> leftChild=byRecursion(left, i-1);
                ArrayList<TreeNode> rightChild=byRecursion(i+1, right);
                for(int j=0;j<leftChild.size();j++)
                {
                    for(int k=0;k<rightChild.size();k++)
                    {
                        TreeNode root=new TreeNode(i);
                        root.left=leftChild.get(j);
                        root.right=rightChild.get(k);
                        res.add(root);
                    }
                }
            }
        }
        return res;
    }

}

下面是C++的做法,这道题很棒,就是构造所有可能的二叉搜索树的情况,说实话我不会做,但是看到了网上的一个做法,感觉也很棒,需要记住好好学习

代码如下:

#include<iostream>
#include <vector>

using namespace std;


/*
struct TreeNode
{
    int val;
    TreeNode *left;
    TreeNode *right;
    TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
*/


class Solution 
{
public:
    vector<TreeNode*> generateTrees(int n) 
    {
        vector<TreeNode*> res;
        if (n <= 0)
            return res;
        res = byDFS(1,n);
        return res;
    }

    vector<TreeNode*> byDFS(int left, int right)
    {
        vector<TreeNode*> res;
        if (left > right)
            res.push_back(NULL);
        else
        {
            for (int i = left; i <= right; i++)
            {
                vector<TreeNode*> leftChild = byDFS(left, i - 1);
                vector<TreeNode*> rightChild = byDFS(i+1, right);
                for (int j = 0; j < leftChild.size(); j++)
                {
                    for (int k = 0; k < rightChild.size(); k++)
                    {
                        TreeNode* root = new TreeNode(i);
                        root->left = leftChild[j];
                        root->right = rightChild[k];
                        res.push_back(root);
                    }
                }
            }
        }
        return res;
    }
};
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值