寻找满足特定层级约束的二叉树中的最大值节点
嘿,这个问题挺有意思的,咱们先把规则理清楚,再一步步拆解解法:
给定一棵二叉树,约束条件如下:每个节点包含不同的自然数;层级从1开始,奇数层级的左子节点值小于其父节点值,右子节点值大于其父节点值;偶数层级则相反,左子节点值大于其父节点值,右子节点值小于其父节点值。现需找出该二叉树中的最大值节点。
核心分析
首先要明确:这个规则只约束直接父子节点的大小关系,跨层级的节点没有大小限制。举个例子:
- 根节点(层级1,奇数)值为10,左子节点(层级2,偶数)值为8(符合左<父);
- 这个左子节点的左子节点(层级3,奇数)值可以是12(符合左>父),而12>根节点的10,这完全符合规则。
也就是说,最大值节点可能出现在树的任意位置,我们没办法通过单一路径直接定位,必须遍历所有可能的节点来确认最大值。
解法一:递归遍历
递归的思路很直观:对于每个节点,最大值要么是它本身,要么在左子树,要么在右子树。我们递归查找左右子树的最大值,再和当前节点比较即可。
先定义二叉树节点结构:
class TreeNode: def __init__(self, val=0, left=None, right=None): self.val = val self.left = left self.right = right
递归实现代码:
def find_max_node(root): # 空树直接返回None if not root: return None # 假设当前节点是最大值 current_max = root # 递归查找左子树的最大值 left_max = find_max_node(root.left) if left_max and left_max.val > current_max.val: current_max = left_max # 递归查找右子树的最大值 right_max = find_max_node(root.right) if right_max and right_max.val > current_max.val: current_max = right_max return current_max
这种解法的时间复杂度是O(n)(每个节点访问一次),空间复杂度是O(h)(h是树的高度,对应递归调用栈的深度)。
解法二:迭代遍历(BFS/DFS)
如果担心递归栈溢出(比如树的高度极大),可以用迭代的方式遍历,比如广度优先搜索(BFS,层序遍历):
from collections import deque def find_max_node(root): if not root: return None max_node = root # 队列存储(节点, 层级),层级其实在这里可以不用,但保留方便理解规则 queue = deque([(root, 1)]) while queue: node, _ = queue.popleft() # 更新最大值节点 if node.val > max_node.val: max_node = node # 将子节点加入队列 if node.left: queue.append((node.left, _ + 1)) if node.right: queue.append((node.right, _ + 1)) return max_node
同样,时间复杂度O(n),空间复杂度最坏情况是O(n)(当树是完全二叉树时,最后一层有n/2个节点)。
关于剪枝优化的思考
可能有人会想:能不能利用层级规则剪枝,减少遍历的节点数?比如奇数层的左子节点<父节点,那左子节点的右子树是不是都比父节点小?
其实大部分情况是这样,但存在例外:比如父节点值15(偶数层),右子节点值10<15,这个右子节点的左子节点值14>10,而14的右子节点值16>14,这时候16>15,也就是父节点的右子树里出现了更大的值。所以剪枝的条件非常复杂,判断的开销可能超过剪枝带来的收益,因此直接遍历所有节点是更简洁可靠的选择。
内容的提问来源于stack exchange,提问作者Nishant

