二叉樹系列---求包含n個節點的二叉查詢樹的種類數
阿新 • • 發佈:2019-01-08
題目1
求包含n個節點的二叉查詢樹的種類數;
方法1
設dp[i]表示共有i個節點時,能產生的BST樹的個數
n == 0 時,空樹的個數必然為1,因此dp[0] = 1
n == 1 時,只有1這個根節點,數量也為1,因此dp[1] = 1
當根節點元素為 1, 2, 3, 4, 5, …, i, …, n時,基於以下原則的BST樹具有唯一性:
以i為根節點時,其左子樹構成為[0,…,i-1],其右子樹構成為[i+1,…,n]構成
因此,dp[i] = sigma(dp[0…k] * dp[k+1…i]) 0 <= k < i - 1
public int numTrees(int n) {
if(n==0||n==1){
return 1;
}
int[] nums=new int[n+1];
nums[0]=1;
nums[1]=1;
for(int i=2;i<=n;i++){
int sum=0;
for(int j=0;j<=i-1;j++){
sum+=nums[j]*nums[i-j-1];
}
nums[i]=sum ;
}
return nums[n];
}
方法2
選擇一個節點,它的左右子樹個數的乘積就是總的個數,可以遞迴解決
public int numTrees2(int n) {
if(n<1){
return 1;
}
int sum=0;
for(int i=1;i<=n;i++){
sum+=numTrees2(i-1)*numTrees2(n-i);
}
return sum;
}
題目2
求包含n個節點(從1到n,n個節點)的所有二叉查詢樹;(不是求個數,而是求所有二叉查詢樹);
思路
/*
* 每次選取一個結點為根(從1到n依次作為根),然後遞迴求解左右子樹的所有結果,
* 最後根據左右子樹的返回的所有子樹,依次選取
* 然後接上(每個左邊的子樹跟所有右邊的子樹匹配,
* 而每個右邊的子樹也要跟所有的左邊子樹匹配,總共有左右子樹數量的乘積種情況),
* 構造好之後作為當前樹的結果返回
*/
實現
public ArrayList<TreeNode> generateTrees(int n) {
return createTrees(1,n);
}
/*
* 每次選取一個結點為根(從1到n依次作為根),然後遞迴求解左右子樹的所有結果,
* 最後根據左右子樹的返回的所有子樹,依次選取
* 然後接上(每個左邊的子樹跟所有右邊的子樹匹配,
* 而每個右邊的子樹也要跟所有的左邊子樹匹配,總共有左右子樹數量的乘積種情況),
* 構造好之後作為當前樹的結果返回
*/
private ArrayList<TreeNode> createTrees(int start, int end) {
ArrayList<TreeNode> res=new ArrayList<TreeNode>();
if(start>end){
res.add(null);
return res;
}
for(int i=start;i<=end;i++){//i作為根
ArrayList<TreeNode> leftList=createTrees(start,i-1);
ArrayList<TreeNode> rightList=createTrees(i+1,end);
/*每個左邊的子樹跟所有右邊的子樹匹配,而每個右邊的子樹也要跟所有的左邊子樹匹配;
* 總共有左右子樹數量的乘積種情況
*/
for(TreeNode left:leftList){
for(TreeNode right:rightList){
TreeNode root=new TreeNode(i); //i作為根
root.left=left;
root.right=right;
res.add(root);
}
}
}
return res;
}