思想
二叉树的核心思想是分治和递归,特点是遍历方式。
解题方式常见两类思路:
- 遍历一遍二叉树寻找答案;
- 通过分治分解问题寻求答案;
遍历分为前中后序,本质上是遍历二叉树过程中处理每个节点的三个特殊时间点:
- 前序是在刚刚进入二叉树节点时执行;
- 后序是在将要离开二叉树节点时执行;
- 中序是左子树遍历完进入右子树前执行;
# 前序
1 node
/ \
2 left 3 right
中左右
# 中序
2 node
/ \
1 left 3 right
左中右
# 后序
3 node
/ \
1 left 2 right
左右中
多叉树只有前后序列遍历,因为只有二叉树有唯一一次中间节点的遍历
题目的关键就是找到遍历过程中的位置,插入对应代码逻辑实现场景的目的。
实例
不同的二叉搜索树 leetcode 96
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
输入:
int,一个整数值
输出:
int,生成并返回由 n 个节点组成且节点值从 1 到 n 互不相同的不同二叉搜索树的种数。
举例:
输入 n = 3
返回 5
1 1 2 3 3
\ \ / \ / /
3 2 1 3 2 1
/ \ / \
2 3 1 2
这个场景的难点在于如何枚举,不能多也不能少。
所有的树的构造都离不开根节点,这个题目可以使用递归方式,假设左右子树都遍历出来,在根节点的位置枚举出来。
- 首先枚举根节点所有的可能性,从 1~n
- 然后左子树和右子树分别遍历出来数量,当前节点的计数是 total + left_tree_count * right_tree_count
- 左右子树通过递归的方式构造,左子树是 low ~ 根节点 -1,右子树是 根节点 + 1 ~ high
- 递归的终止条件是 low > high
二叉树的数据存储可以使用链表,也可以使用数组,往往数组更容易表达,根节点从 index=1 处开始存储,浪费 index=0 的位置
left_child = 2 * parent
right_child = 2 * parent + 1 parent = child // 2
编码
class TreeNode:
def __init__(self, val=0, left=None, right=None):
self.val = val
self.left = left
self.right = right
def unique_binary_search_tree(n: int) -> int:
# k:v = 'low:high':count
memo = {}
def build(low: int, high: int) -> int:
# 递归终止条件
if low >= high:
return 1
# 剪枝,避免重复遍历,提高效率
key = str(low) + ':' + str(high)
if key in memo:
return memo[key]
count = 0
# root 遍历 [low, high] 区间的所有值
for i in range(low, high + 1):
# 递归构建左右子树
left_count = build(low, i - 1)
right_count = build(i + 1, high)
count += left_count * right_count
memo[key] = count
return count
# 边界条件
if n == 0:
return 0
# 递归构建不同的二叉搜索树
return build(1, n)
相关
二叉树 0
二叉树 1
二叉树 2
二叉树 3
二叉树 4
二叉树 5
二叉树 6
二叉树 7
二叉树 8
二叉树 9
二叉树 10
二叉树 11
二叉树 12
二叉树 13
二叉树 14
二叉树 15
二叉树 16
二叉树 17
二叉树 18
二叉树 19
二叉树 20
二叉树 21
二叉树 22
二叉树 23
二叉树 24
二叉树 25