【LeetCode算法学习笔记】二叉搜索树第三期

labuladong算法公众号学习笔记
labuladong算法公众号学习笔记
labuladong算法公众号学习笔记


如何计算所有合法BST

不同二叉搜索树

穷举法
二叉树算法的关键在于明确根节点需要做什么

int numTrees(int n){
    //计算闭区间[1,n]组成的BST个数
    return count(1,n);
}
/*计算闭区间[lo,hi]组成的BST个数*/
int count(int lo,int hi)
{
    if(lo>hi) return 1;
    int res=0;
    for(int i = lo; i <= hi; i++)
    {
        //i为根结点root
        int left = count(lo,i-1);
        int right = count(i+1,hi);
        //左右子树的组合乘积数是BST的总数
        res+=left*right; 
    }
    return res;
}

上述代码虽然可以解决问题,但时间复杂度很高,而且存在子重叠问题。
消除重叠子问题的方式是加一个备忘录:

//备忘录
int[][] memo;

int numTrees(int n){
    //备忘录初始化为0
    memo=new int[n+1][n+1];
    return count(1,n);
}
int count(int lo,int hi){
    if(lo>hi) return 1;
    //查找备忘录
    if(memo[lo][hi] != 0){
        return memo[lo][hi];
    }
    int res=0;
    for(int i = lo; i <= hi; i++){
        int left=count(lo,i-1);
        int right=count(i+1,hi);
        res+=left*right;
    }
    //将结果存入备忘录
    memo[lo][hi]=res;
    return res;
}

不同二叉搜索树II

思路同上:
1、穷举root节点的所有可能
2、递归构造出左右子树的所有合法BST
3、给root节点穷举所有左右子树的组合

public List<TreeNode> generateTrees(int n){
    if(n==0) return new LinkedList<>();
    //构造闭区间[1,n]组成的BST
    return build(1,n);
}
List<TreeNode> build(int lo,int hi){
    List<TreeNode> res = new LinkedList<>();
    if(lo>hi){
        res.add(null);
        return res;
    }
    //1、穷举root节点的所有可能
    for(int i = lo; i <= hi ; i++){
        //2、递归构造出左右子树的所有合法BST
        List<TreeNode> leftTree = build(lo,i-1);
        List<TreeNode> rightTree = build(i+1,hi);
        //3、给root节点穷举所有左右子树的组合
        for(TreeNode left : leftTree){
            for(TreeNode right : rightTree){
                //i作为根节点root的值
                TreeNode root = new TreeNode(i);
                root.left=left;
                root.right=right;
                res.add(root);
            }
        }
    }
    return res;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值