1. 问题背景与理解
今天我们来拆解一道二叉树遍历的经典题目 - LeetCode 1372。这道题要求我们找出二叉树中最长的"交错路径"。所谓交错路径,是指路径上的节点交替满足"左-右-左"或"右-左-右"的走向规则。
举个例子,假设我们有以下二叉树:
code复制 1
\
2
/ \
3 4
\ \
5 6
/
7
其中最长的交错路径是[2,3,4,6],长度为3(路径长度定义为边的数量)。
2. 解题思路分析
2.1 问题分解
这道题的核心在于如何高效地遍历二叉树,同时记录每个节点的两种可能状态:
- 当前节点作为左子节点时的最长交错路径
- 当前节点作为右子节点时的最长交错路径
2.2 递归解法
我们可以采用深度优先搜索(DFS)的递归方式来解决这个问题。对于每个节点,我们需要考虑两种情况:
- 如果当前节点是父节点的左子节点,那么下一步只能往右走
- 如果当前节点是父节点的右子节点,那么下一步只能往左走
2.3 动态规划思想
这个问题实际上可以用动态规划的思路来解决。我们可以定义两个状态:
- left[node]:以node为起点,第一步向左走的最长交错路径
- right[node]:以node为起点,第一步向右走的最长交错路径
3. 具体实现方案
3.1 递归实现代码
python复制class Solution:
def longestZigZag(self, root: Optional[TreeNode]) -> int:
self.max_len = 0
def dfs(node, is_left, length):
if not node:
return
self.max_len = max(self.max_len, length)
if is_left:
dfs(node.left, False, length + 1) # 继续交错
dfs(node.right, True, 1) # 重新开始
else:
dfs(node.right, True, length + 1) # 继续交错
dfs(node.left, False, 1) # 重新开始
dfs(root, True, 0) # 假设父节点在左边
dfs(root, False, 0) # 假设父节点在右边
return self.max_len
3.2 迭代实现方案
对于不喜欢递归的开发者,我们也可以用迭代的方式实现:
python复制class Solution:
def longestZigZag(self, root: Optional[TreeNode]) -> int:
if not root:
return 0
stack = [(root, True, 0), (root, False, 0)]
max_len = 0
while stack:
node, is_left, length = stack.pop()
max_len = max(max_len, length)
if is_left:
if node.left:
stack.append((node.left, False, length + 1))
if node.right:
stack.append((node.right, True, 1))
else:
if node.right:
stack.append((node.right, True, length + 1))
if node.left:
stack.append((node.left, False, 1))
return max_len
4. 复杂度分析与优化
4.1 时间复杂度
两种实现方式的时间复杂度都是O(n),其中n是树中节点的数量,因为每个节点最多被访问两次(作为左子节点和右子节点各一次)。
4.2 空间复杂度
递归实现的空间复杂度取决于树的高度,最坏情况下是O(n)(当树退化为链表时)。迭代实现的空间复杂度也是O(n)。
4.3 优化思路
我们可以通过记忆化搜索来优化递归实现,避免重复计算。不过对于这个问题,由于每个节点的状态只依赖于其子节点,所以标准的DFS已经足够高效。
5. 常见错误与调试技巧
5.1 常见错误
- 忘记初始化最大长度变量
- 混淆路径长度的计算方式(节点数 vs 边数)
- 没有考虑从根节点开始的两种情况(假设父节点在左或在右)
5.2 调试技巧
- 打印递归路径:在递归函数中添加打印语句,跟踪路径走向
- 小规模测试:先用简单的二叉树测试,如只有3个节点的树
- 边界测试:测试空树、只有左子树或只有右子树的特殊情况
6. 实际应用场景
这类二叉树路径问题在实际开发中有多种应用场景:
- 文件系统目录遍历:查找满足特定条件的路径
- 组织结构分析:分析公司汇报路径中的特定模式
- 游戏AI路径规划:寻找符合特定移动规则的路径
7. 扩展思考
这道题可以延伸出几个变种问题:
- 找出所有最长交错路径而不仅仅是长度
- 考虑带权二叉树,找出权重和最大的交错路径
- 在多叉树中定义并寻找交错路径
对于想进一步挑战的开发者,可以尝试解决这些变种问题。在实际面试中,面试官也可能会基于原始问题提出这些扩展问题来考察候选人的思维能力。