高效生成含N个叶节点、深度为D的随机非对称二叉树
高效生成指定叶节点数且深度受限的随机二叉树
核心思路
放弃“随机生成后筛选”的低效方式,直接基于动态规划+概率抽样构造符合要求的树:
- 按叶节点总数N,递归分配左右子树的叶节点数量,确保每棵子树的叶节点数≥1(避免退化的对称结构);
- 递归构造时严格控制剩余深度,保证最终树的深度不超过D;
- 从所有合法的叶节点分配组合中均匀抽样,确保生成的树分布无偏。
前置合法性校验
生成前先确认输入参数是否合法:
- 若要生成非对称树,需满足N≥2;
- 深度为D的二叉树最多容纳
2^(D-1)个叶节点(满二叉树情况),若N超过该值则无法生成,直接抛出异常。
算法步骤
- 递归构造逻辑:
- 若当前节点剩余允许深度为1,说明该节点必须是叶节点,直接返回;
- 若剩余深度>1且需要生成k个叶节点(k≥2):
- 枚举所有合法的左子树叶节点数
l:1≤l≤k-1,且l和k-l都不超过剩余深度-1对应的最大叶节点数(即2^(剩余深度-2)); - 从合法的
(l, k-l)组合中随机选一组; - 递归构造左右子树,分别对应
l和k-l个叶节点,剩余深度减1。
- 枚举所有合法的左子树叶节点数
- 打破对称优化:
- 当选中的
l和k-l相等时,50%概率交换左右子树的构造顺序,避免生成完全对称的树结构。
- 当选中的
代码示例(Python)
import random class TreeNode: def __init__(self, val=None): self.val = val self.left = None self.right = None def is_valid(N, D): # 校验参数合法性:非对称要求N≥2,且N不超过深度D对应的最大叶节点数 if N < 2: return False max_possible_leaves = 2 ** (D - 1) return N <= max_possible_leaves def generate_random_tree(N, D): if not is_valid(N, D): raise ValueError("N must be ≥2 and ≤ 2^(D-1)") def _build(required_leaves, remaining_depth): # 剩余深度为1时,当前节点必须是叶节点 if remaining_depth == 1: return TreeNode(random.randint(1, 100)) # 随机生成节点值,可自定义 # 枚举所有合法的左子树叶节点数 max_sub_leaves = 2 ** (remaining_depth - 2) valid_left_counts = [] for l in range(1, required_leaves): right_count = required_leaves - l if l <= max_sub_leaves and right_count <= max_sub_leaves: valid_left_counts.append(l) # 随机选择左子树的叶节点数 left_count = random.choice(valid_left_counts) right_count = required_leaves - left_count # 构造当前节点及子树 node = TreeNode(random.randint(1, 100)) node.left = _build(left_count, remaining_depth - 1) node.right = _build(right_count, remaining_depth - 1) # 50%概率交换左右子树,打破对称 if left_count == right_count and random.random() < 0.5: node.left, node.right = node.right, node.left return node return _build(N, D) # 测试:生成10个叶节点、深度不超过4的随机二叉树 tree = generate_random_tree(10, 4)
效率优化建议
- 预计算所有
(required_leaves, remaining_depth)对应的合法左子树数量列表,避免递归时重复枚举; - 若需批量生成树,可缓存合法组合的抽样结果,进一步提升速度。
内容的提问来源于stack exchange,提问作者user12953893
相关产品推荐
相关产品推荐

