数据结构与算法之 leetcode 二叉树最近公共祖先 递归 / 迭代

数据结构与算法阿木 发布于 2 天前 1 次阅读


二叉树最近公共祖先问题解析与代码实现

在二叉树中,最近公共祖先(Lowest Common Ancestor,LCA)问题是一个经典且具有挑战性的算法问题。给定一个二叉树和一个节点对,我们需要找到这两个节点的最近公共祖先。这个问题在计算机科学中有着广泛的应用,例如在社交网络中查找共同好友、在文件系统中查找共同父目录等。

本文将围绕二叉树最近公共祖先问题,从递归和迭代两种方法进行解析,并给出相应的代码实现。文章将分为以下几个部分:

1. 问题背景与定义

2. 递归方法解析与代码实现

3. 迭代方法解析与代码实现

4. 两种方法的比较与总结

1. 问题背景与定义

1.1 问题背景

假设我们有一个二叉树,如下所示:


3


/


5 1


/ /


6 2 0 8


/


7 4


我们需要找到节点 `5` 和节点 `1` 的最近公共祖先。

1.2 定义

最近公共祖先(LCA)是指二叉树中两个节点的最低公共祖先。如果节点 `p` 和节点 `q` 有一个共同的祖先节点 `u`,且没有比 `u` 更低的公共祖先,则节点 `u` 是节点 `p` 和节点 `q` 的最近公共祖先。

2. 递归方法解析与代码实现

递归方法是一种直观且易于理解的方法。其基本思想是:如果当前节点是 `p` 或 `q`,则返回当前节点;如果当前节点的左子树或右子树中包含 `p` 和 `q`,则返回包含这两个节点的子树的根节点。

以下是递归方法的代码实现:

python

class TreeNode:


def __init__(self, x):


self.val = x


self.left = None


self.right = None

def lowestCommonAncestor(root, p, q):


if root is None or root == p or root == q:


return root


left = lowestCommonAncestor(root.left, p, q)


right = lowestCommonAncestor(root.right, p, q)


if left is None:


return right


if right is None:


return left


return root


3. 迭代方法解析与代码实现

迭代方法通常比递归方法更节省内存,因为它不需要在递归过程中保存调用栈。迭代方法的基本思想是:使用两个指针分别从根节点向下遍历,直到找到两个指针指向的节点为 `p` 和 `q`,然后向上回溯找到最近公共祖先。

以下是迭代方法的代码实现:

python

class TreeNode:


def __init__(self, x):


self.val = x


self.left = None


self.right = None

def lowestCommonAncestor(root, p, q):


parent = {root: None}


stack = [root]


while p not in parent or q not in parent:


node = stack.pop()


if node.left:


parent[node.left] = node


stack.append(node.left)


if node.right:


parent[node.right] = node


stack.append(node.right)


ancestors_p = set()


while p:


ancestors_p.add(p)


p = parent[p]


while q not in ancestors_p:


q = parent[q]


return q


4. 两种方法的比较与总结

4.1 比较分析

- 递归方法:易于理解,代码简洁,但可能存在栈溢出的问题,且在递归过程中会消耗更多的内存。

- 迭代方法:节省内存,但代码相对复杂,需要手动维护指针和父节点信息。

4.2 总结

在解决二叉树最近公共祖先问题时,递归和迭代方法各有优缺点。在实际应用中,我们可以根据具体情况选择合适的方法。如果对内存消耗比较敏感,可以选择迭代方法;如果代码可读性和简洁性更重要,可以选择递归方法。

二叉树最近公共祖先问题是一个具有挑战性的算法问题,通过递归和迭代两种方法,我们可以深入理解二叉树遍历和递归/迭代算法的原理。在实际应用中,我们可以根据具体需求选择合适的方法,以提高代码的效率和可读性。