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;
}