---
# System prepended metadata

title: Leetcode --- Unique Binary Search Trees II(Medium)
tags: [DP, Leetcode, Medium, Tree]

---

Leetcode --- Unique Binary Search Trees II(Medium)
===

## Description

Given an integer n, return all the structurally unique BST's (binary search trees), which has exactly n nodes of unique values from 1 to n. Return the answer in any order.

**給n表示所有數字1~n,將所有用這些數字所組成的不同構的BST列出來.**

### Example
```
1          1            2           3         3
 \          \         /   \        /         /
  2          3       1     3      1         2
   \        /                      \       /
    3      2                        2     1
```
**Input**: n = 3
**Output**: [[1,null,2,null,3],[1,null,3,2],[2,1,3],[3,1,null,null,2],[3,2,null,1]]

### Constraint 
* 1 <= n <= 8

## Solutions

* **Method 1: Recursion**

所有不同的組合的解 => root =1,2,...,n都要排列過,所以拆成
Sol(n) = sol(root=1) +sol(root=2) +... + sol(root=n)
再帶入BST特性:若root = i => 左子會有**1~ i-1**的數字做組合,右子會有**i+1~n**的數字做組合,再遞迴.

### Implement code 
```java=
class Solution {
    public List<TreeNode> generateTrees(int n) {
       return helper(1,n);
    }
    private List<TreeNode> helper(int st,int ed)
    {
        List<TreeNode> res =new ArrayList<>();
        if(st>ed)
        {
            res.add(null);
            return res;
        }
        for(int i =st ; i<=ed ;i++)
        {
            List<TreeNode> left = helper(st,i-1);
            List<TreeNode> right = helper(i+1,ed);
            for(TreeNode l : left)
                for(TreeNode r : right)
                {
                    TreeNode ans = new TreeNode(i,l,r);
                    res.add(ans);
                }
        }
         return res;
    }
}
```
line 8: 停止條件:當要排列的數字大於root則填null
line 17,18:將所有得到的左右子做組合

### Submission on Leetcode

Runtime: **1 ms, faster than 93.80%** of Java online submissions for Unique Binary Search Trees II.
Memory Usage: **39.6 MB, less than 61.99%** of Java online submissions for Unique Binary Search Trees II.

---

* **Method 2: DP**
觀察n=2,n=3

```
n=2
 
1         2   
 \       /
  2     1

n=3

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

新插入的數字一定大於前一個case,==**所以只會出現在root** , **root.rightChild** , **root.rightChild.rightChild** , **....**==
所以變成
![tree](https://i.imgur.com/nSheLm6.jpg)

==若插入位置原本有node則此串node變成新node的左子==

=>

```
Org:
        1
         \
          2
           \
            3
Insert(4)在pos 1

        1
         \
          4
         /
       2
        \
         3

```


### Implement code
```java=
class Solution {
    public List<TreeNode> generateTrees(int n) {
        List<TreeNode> ans = new ArrayList<>();
        if(n==0)
        {
            ans.add(null);
            return ans;
        }
        
        List<TreeNode> preL = generateTrees(n-1);
        
        for(TreeNode pre : preL)
        {
            for(int i =0;i<n;i++)
            {
                TreeNode res = insertcur(pre,i,n);
                if(res != null)
                    ans.add(res);
            }
        }
        return ans;
    }
    private TreeNode detect(TreeNode preT ,int pos)
    {  
        int i =0;
        while(i<pos-1)
        {
            if(preT ==null)
            {
                break;
            }
            preT =preT.right ;
            i++;
        }
        return preT;
    }
    private TreeNode insertcur(TreeNode pre,int pos,int cur)
    {
        TreeNode preT = copyT(pre);
        TreeNode head =preT;
        TreeNode curT = new TreeNode(cur);
        if(pos ==0)
        {
            curT.left =preT;
            return curT;
        }
        TreeNode part = detect(preT,pos);
        if(part ==null)
        {
            return null;
        }
            
        if(part.right == null)
        {
            part.right = curT;
        }
        else
        {
            curT.left = part.right;
            part.right =curT;
        }
        return head;
       
    }
    private TreeNode copyT(TreeNode T)
    {
        if(T ==null)
            return null;
        TreeNode newT = new TreeNode();
        newT.val =T.val;
        newT.left = copyT(T.left);
        newT.right = copyT(T.right);
        return newT;
    }
}
```

* function:detect(TreeNode preT ,int pos)
探測第pos位置的右子是否為null,root 為 position 0,若尚未探到目標pos則已為null則此case須被丟棄,直接回傳null.
為了之後好操作少探測一次,之後可以用preT.right來增減樹

* function:insertcur(TreeNode pre,int pos,int cur)
在n-1的解pre中,對第pos位置的右子插入Node(cur)
必須用copyTree來保護,因為一個pre會被操作很多次,把pos=0作為特別解,額外處理,其他部分做detect來看要不要做修正,detect=null時為被丟棄的case

* Main
對每一個上一個解,把新node分別嘗試插在root,root.right ..... 

### Submission on Leetcode

Runtime: **1 ms, faster than 93.76%** of Java online submissions for Unique Binary Search Trees II.
Memory Usage: **39.8 MB, less than 31.59%** of Java online submissions for Unique Binary Search Trees II.


###### tags: `Leetcode` `Medium` `DP` `Tree`