python练习——二叉搜索树

二叉搜索树练习——不同的二叉搜索树、不同的二叉搜索树 II

二叉搜索树

二叉搜索树是一种特殊的二叉树,它的左子节点小于根节点,根节点小于右子节点。如果使用中序排列的话,得到的结果是一个升序排列。如图所示的二叉搜索树的中序排列为
[ 1 , 2 , 4 , 5 , 8 , 9 , 10 ] \left[1,2,4,5,8,9,10\right] [1,2,4,5,8,9,10]
在这里插入图片描述

Leetcode不同的二叉搜索树

问题描述
给定一个整数n,求以1至n为节点组成的二叉搜索树有多少种?

示例
输入: 3
输出: 5
在这里插入图片描述

思考
首先给定一个数n,根据这个数生成一个升序列表,先考虑根节点root,每个数都可以成为根节点root,因此需要一个for循环来确定根节点root的值;
在这里插入图片描述
然后是根节点往下的左子树和右子树。这时将刚刚root节点左边的数作为左子树的根节点的候选数,右边的数作为右子树的根节点的候选数。
在这里插入图片描述
如图所示,左子树的根节点root有三种可能,右子树的根节点root有一种可能,这时从左子树的三种可能中依次选取数值作为根节点,由于此时右子树仅有一种可能,那么就不需要针对右子树进行向下传递了,并且要返回值1,表示仅有一种可能。
在这里插入图片描述
此时发现,有的左子树或右子树不存在,因此需要返回值1,表示当前节点的左子树或右子树仅有一种可能,即null。接下来继续向下传递。
在这里插入图片描述
将左右子树候选个数为1或0的情况,返回值1,表示此时已经只有确定的二叉搜索树了,不存在候选的情况。最后开始回溯,从最下面的结点开始,将他们的可能的左子树的个数乘上可能的右子树的个数,即为当前节点为根节点的二叉搜索树的可能的个数。

需要注意的是,直接使用递归算法,会出现超时的情况,这是因为数据集是一堆整数,假如第一个数是5,代表此时计算的二叉搜索树有五个节点;接下来的数是10,表示此时计算的二叉搜索树的节点个数是10,其中当递归过程中,出现子树可能的根节点个数为5时,会重新进行计算,而不是用之前一次计算中,节点数为5时的结果,这样造成了重复计算的情况,会大大延长计算时间。因此在进行递归的过程中,保存每次计算的结果,以便后续调用,减少计算时间。

具体代码如下

class Solution:
	#定义一个字典,存储每次计算的结果
    save_result = dict()
    def numTrees(self, n: int) -> int:
    	#当出现之前已经计算过的情况,调用之前的结果
    	if n in self.save_result:
    		return self.save_result.get(n)
    	#当左子树或右子树的叶子节点个数为0或1时,终止递归,并返回1
    	if n <= 1:
    		return 1
    	result = 0
    	#递归过程
    	for root in range(1, n + 1):
    		result += self.numTrees(root - 1) * self.numTrees(n - root)
    	self.save_result[n] = result
    	return result

Leetcode不同的二叉搜索树 II

问题描述
给定一个整数n,生成所有由1至n为节点所组成的 二叉搜索树 。

示例
输入: 3
输出: [[1,null,3,2],[3,2,null,1],[3,1,null,null,2],[2,1,3],[1,null,2,null,3]]
在这里插入图片描述
思考
首先还是要先考虑根节点root,用for循环来遍历一组数,让每个数都作为根节点。

然后将root两边的数进行划分,左侧作为左子树的节点,右侧作为右子树的节点,然后使用for循环嵌套结构,将当前遍历的左侧数组的数字作为当前根节点的左子树根节点,右侧数组的数字作为当前根节点的右子树根节点。

接下来对每组数都进行相同的操作,即依次选择根节点,作为左右子树的根节点,并划分数组。当最后数组中不存在数字时,即已经确定了一棵二叉搜索树时,停止遍历。

具体代码如下

class TreeNode:
    def __init__(self, val=0, left=None, right=None):
        self.val = val
        self.left = left
        self.right = right
class Solution:
    def generateTrees(self, n: int) -> List[TreeNode]:
    	if n == 0: return []
    	def loop(number_list):
    		if len(number_list) == 0:
    			return [None]
    		result_tree = []
    		for root in range(len(number_list)):
    			for left_number in loop(number_list[: root]):
    				for right_number in loop(number_list[root + 1:]):
    					tree_node = TreeNode(number_list[root])
    					tree_node.left = left_number
    					tree_node.right = right_number
    					result_tree.append(tree_node)
    		return result_tree
    	return loop(list(range(1, n+1)))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值