有关树的问题时,一定要先想到回溯法,因为树独特的结构,使得问题在很多情况下可以由整个树的问题分解为左子树和右子树的问题,从而逐步解决问题。
二叉搜索树关键的性质是根节点的值大于左子树所有节点的值,小于右子树所有节点的值,且左子树和右子树也同样为二叉搜索树。这道题的目标是找到有n个节点的所有的不同结构的二叉搜索树。而由于这些二叉搜索树的左右子树也均为二叉搜索树,所以可以将问题由之前的找[1, n]范围内的所有二叉搜索树,转化为找[1, i-1]、[i+1, n]范围内的所有二叉搜索树,也就是将问题分解为找以i为根节点的两个左右子树,其中i的范围是[1, n]。一直往下回溯,直到该范围中只有1个值,或者该范围的左边界大于右边界,这两种情况下,就说明回溯到了树的叶子。范围中只有1个值,代表着回溯到了该值的叶子节点。左边界大于右边界,说明不存在该范围内子树,为None。
在做树的题目的时候,一定要注意叶子节点和空树的判断。这两种情况下,算法不能继续回溯,而是需要返回值或者做其他操作,需要特殊处理。
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def recurse(self, begin: int, end: int) -> List[TreeNode]:
Result = []
# 到达叶子节点
if begin == end:
return[TreeNode(val=begin)]
# 不存在该范围内子树,为None
if begin > end:
return [None]
for i in range(begin, end+1):
LeftTree = self.recurse(begin, i-1)
RightTree = self.recurse(i+1, end)
for l in LeftTree:
for r in RightTree:
center = TreeNode(val=i)
center.left = l
center.right = r
Result.append(center)
return Result
def generateTrees(self, n: int) -> List[TreeNode]:
if n <= 0:
return []
return self.recurse(1, n)
好久不练,手生了。我果然还是个菜鸡。今天随手打开了之前打ACM时自己写过的题解,觉得自己之前比现在厉害多了哈哈哈哈。而且现在一直在用python写代码,很多C++语法都已经忘了,需要重新学习了。