LeetCode --- 不同的二叉搜索树 解题思路与疑惑
题目:
提示: 0 <= n <= 8
BST:
二叉搜索树(Binary Search Tree,BST),又称为二叉排序树(Binary Sort Tree,BST),具有以下性质:
- 若左子树不为空,则左子树上所有节点的值均小于等于根节点值。
- 若右子树不为空,则右子树上所有节点的值均大于等于根节点值。
- 左、右子树也分别是BST。
BST数据结构:
下面二叉搜索树的数据结构:
class TreeNode:
def __init__(self, val=0):
self.val = val
self.left = None
self.right = None
BST基本操作的编程(很多操作此程序用不到):
class OperationTree:
# 二叉搜索树插入操作
def insert(self, root, val):
if root == None:
root = TreeNode(val)
elif val < root.val:
root.left = self.insert(root.left, val)
elif val > root.val:
root.right = self.insert(root.right, val)
return root
# 查询二叉搜索树是否含有特定数字
def query(self, root, val):
if root == None:
return False
elif root.val == val:
return True
elif val < root.val:
return self.query(root.left, val)
elif val > root.val:
return self.query(root.right, val)
# 寻找BST最小值
def findMin(self, root):
if root.left:
return self.findMin(root.left)
else:
return root
# 寻找BST最大值
def findMax(self, root):
if root.right:
return self.findMax(root.right)
else:
return root
# 删除 BST的某个节点
def delNode(self, root, val):
if root == None: #被删除的节点不存在,不进行任何操作返回
#print("被删除的节点:%d不存在!"%val)
return
# 左子树递归删除目标节点
if val < root.val:
root.left = self.delNode(root.left, val)
# 右子树递归删除目标节点
elif val > root.val:
root.right = self.delNode(root.right, val)
else:
# 既有左子树,又有右子树,则需找到右子树中的最小值节点
if root.left and root.right:
temp = self.findMin(root.right)
root.val = temp.val
root.right = self.delNode(root.right, temp.val)
# 左右子树都为空
elif root.right == None and root.left == None:
root = None
# 只有左子树
elif root.right == None:
root = root.left
# 只有右子树
elif root.left == None:
root = root.right
return root
# 中序遍历、打印二叉搜索树:打印的是一个有序数列
def printTree(self, root):
if root == None:
return
self.printTree(root.left)
print(root.val, end = ' ')
self.printTree(root.right)
从题目可以看到打印方式是层次优先的遍历打印。下面是按层次遍历打印二叉树(包含了部分null节点的输出)函数:
# 层次优先遍历打印二叉树
def LevelTree(self, root):
result_list = []
# 如果根节点为空,则返回空列表
if root is None:
return
# 模拟一个队列储存节点
stack = []
# 首先将根节点入队
stack.append(root)
# 列表为空时,循环终止
while len(stack) != 0:
length = len(stack)
for i in range(length):
# 判断是否只剩下None
if set(stack) == {None}:
stack = []
break
# 将同层节点依次出队
top = stack.pop(0)
if top is None:
result_list.append('null')
# print('null', end = ' ')
continue
if top.left is None:
stack.append(None)
elif top.left is not None:
# 非空左孩子入队
stack.append(top.left)
if top.right is None:
stack.append(None)
elif top.right is not None:
# 非空右孩子入队
stack.append(top.right)
result_list.append(top.val)
# print(top.val, end = ' ')
return result_list # 二叉树水平遍历的结构,保存在列表中返回
可以写个简单的脚本测试能否输出正确的树结构:
List = [1,2,3]
root = None
op = OperationTree()
for val in List:
root = op.insert(root, val)
print("按层次打印二叉搜索树:", end = ' ')
print(op.levelOrder(root))
主程序分析
后面写的是主程序逻辑结构,思路是根据输入的n值生成 n! 种[1,2,3,...,n]的不同的排序存入数组,然后对数组内每一个元素构建二叉树并用LevelTree函数返回其结构,判断这个结构是否已经存在过,不存在就扩展,存在就跳过(过滤重复输出的结构)。
这句话的意思可以这样理解:
n=3的情况下,[2,1,3]、[2,3,1]是二叉搜索树两个不同的生成顺序,但是生成的BST一样的:
在n较大的时候,这种差别体现的尤其明显。因此需要过滤判断。
完整代码:
#coding=utf-8
import itertools
def permutation(li):
return list( itertools.permutations(li) )
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
class OperationTree:
# 二叉搜索树插入操作
def insert(self, root, val):
if root == None:
root = TreeNode(val)
elif val < root.val:
root.left = self.insert(root.left, val)
elif val > root.val:
root.right = self.insert(root.right, val)
return root
# 层次优先遍历打印二叉树
def LevelTree(self, root):
result_list = []
# 如果根节点为空,则返回空列表
if root is None:
return
# 模拟一个队列储存节点
stack = []
# 首先将根节点入队
stack.append(root)
# 列表为空时,循环终止
while len(stack) != 0:
length = len(stack)
for i in range(length):
# 判断是否只剩下None
if set(stack) == {None}:
stack = []
break
# 将同层节点依次出队
top = stack.pop(0)
if top is None:
result_list.append('null')
# print('null', end = ' ')
continue
if top.left is None:
stack.append(None)
elif top.left is not None:
# 非空左孩子入队
stack.append(top.left)
if top.right is None:
stack.append(None)
elif top.right is not None:
# 非空右孩子入队
stack.append(top.right)
result_list.append(top.val)
# print(top.val, end = ' ')
return result_list
class Solution:
def generateTrees(self, n):
op = OperationTree()
src_List = [i for i in range(1,n+1)]
tree_list = permutation(src_List) # n!个元素(输入结构)
tree_print_list = [] # 输出结构
for tree in tree_list:
root = None
for val in tree:
root = op.insert(root, val)
tree_print = op.LevelTree(root)
if tree_print not in tree_print_list:
tree_print_list.append(tree_print)
del root
return tree_print_list
if __name__ == "__main__":
n = int(input())
X = Solution()
print(X.generateTrees(n))
测试n=3:
测试n=4:
看起来应该是对的,可是提交leetcode遇到了麻烦:
输出为什么是空的而stdout是理想的输出。。。
其次'null'与null有区别吗。。。
最最最难受的是提交检验失败了。