###### tags: `Leetcode` `medium` `dynamic programming` `tree` `python` # 95. Unique Binary Search Trees II ## [題目連結:] https://leetcode.com/problems/unique-binary-search-trees-ii/ ## 題目: 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**. ![](https://i.imgur.com/k8TKtwY.png) #### [圖片來源:] https://leetcode.com/problems/unique-binary-search-trees-ii/ ## 解題想法: 兄弟題目: [96. Unique Binary Search Trees](/0tFv4d9vSM-WIC_uKucQ5A) * [96. Unique Binary Search Trees](/0tFv4d9vSM-WIC_uKucQ5A) 為求n個node能組成之BST之個數,而此題為要求,輸出實際tree構造 * dfs: * 傳遞參數: (start,end) * 表示由start到end的node構成的BST * ex: (1,n) : 由1~n構成 * ex: (2,4) : 由node 2,3,4構成 * 終止條件: * 若start>end: * return [None] * 每次選i為root: * 遞迴求左子樹: Left_Tree * 可由start~(i-1)的node構成 * 遞迴求右子樹: Right_Tree * 可由(i+1)~end的node構成 * ex: start=1 end=7 * i=4 * 左子樹=dfs(1,3) -> 由1,2,3構成 * 右子樹=dfs(5,7) -> 由5,6,7構成 * 連結: * 因為遞迴求的左右子樹,分別回傳list,該list中存的元素為root,每個root都有其其獨特的結構 * 因此連結方式為 ``` python= for l_root in Left_Tree: for r_root in Right_Tree: root = TreeNode(i) root.left =l_root root.right=r_root res.append(root) ``` ## Python: (dfs) ``` python= #https://www.twblogs.net/a/5cba808fbd9eee0f00a2573e class TreeNode(object): def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right def insertLeft(self,node): if self.left==None: self.left = TreeNode(node) else: self.left.insertLeft(node) def insertRight(self,node): if self.right==None: self.right=TreeNode(node) else: self.right.insertRight(node) def printTree(self): root = self que = [root] res=[] while que: root=que.pop(0) res.append(root.val) if root.left: que.append(root.left) if root.right: que.append(root.right) print(res) class Solution(object): def generateTrees(self, n): """ :type n: int :rtype: List[TreeNode] """ return self.dfs(1,n) #由start到end的node構成的BST def dfs(self,start,end): res = [] if start>end: return [None] #選i為root for i in range(start,end+1): #以i為root #左子數: 可由start~i-1的node構成 #右子數: 可由i+1~end的node構成 Left_Tree = self.dfs(start,i-1) Right_Tree = self.dfs(i+1,end) #連結root for l_root in Left_Tree: for r_root in Right_Tree: root = TreeNode(i) root.left =l_root root.right=r_root res.append(root) return res result = Solution() ans = result.generateTrees(3) for i in range(len(ans)): ans[i].printTree() ''' [1, 2, 3] [1, 3, 2] [2, 1, 3] [3, 1, 2] [3, 2, 1] ''' ``` ## Python: (dp+dfs) * 優化: * 使用字典path紀錄已使用過的pair(start,end) * 若該pair已在path 直接回傳使用即可 ``` python= class Solution(object): def generateTrees(self, n): """ :type n: int :rtype: List[TreeNode] """ self.path={} return self.dfs(1,n) def dfs(self,start,end): if start>end: return [None] if start==end: #自己一點構成樹 return [TreeNode(start)] #若該pair已在path 直接回傳使用即可 if (start,end) in self.path: return self.path[(start,end)] res=[] #由start~end的node構成BST for i in range(start,end+1): Left_Tree=self.dfs(start,i-1) Right_Tree=self.dfs(i+1,end) for rootL in Left_Tree: for rootR in Right_Tree: root=TreeNode(i) root.left=rootL root.right=rootR res.append(root) #存入此start~end所構成的BST的所有組合結構 self.path[(start,end)]=res return res ```