返回

一道考验思考,颇具脑洞的 leetcode 题目,测试你的解决问题能力和代码实现能力

前端

大家好,欢迎来到我的刷题打卡专栏。今天,我们一起来挑战 LeetCode 236 题“二叉树的最近公共祖先”。这道题要求你找出二叉树中两个指定节点的最近公共祖先,即这两个节点的共同祖先中深度最大的一个。

题目

给定一个二叉树,找出两个指定节点 p 和 q 的最近公共祖先。

示例:

给定以下二叉树:

        1
       / \
      2   3
     / \
    4   5

若 p = 4,q = 5,则它们的最近公共祖先是节点 2。

解法:

这道题可以采用递归的方法来解决。递归的基本思想是将一个大问题分解成一系列较小的子问题,然后递归地解决这些子问题,最后将子问题的解组合起来得到大问题的解。

在二叉树中,最近公共祖先可以通过以下步骤来找到:

  1. 如果 p 和 q 都在左子树中,则最近公共祖先在左子树中。
  2. 如果 p 和 q 都在右子树中,则最近公共祖先在右子树中。
  3. 如果 p 和 q 分别在左子树和右子树中,则最近公共祖先是当前节点。

根据以上步骤,我们可以写出以下递归算法:

def lowest_common_ancestor(root, p, q):
  if not root:
    return None

  # 如果 p 和 q 都在左子树中
  if root.val > p.val and root.val > q.val:
    return lowest_common_ancestor(root.left, p, q)

  # 如果 p 和 q 都在右子树中
  if root.val < p.val and root.val < q.val:
    return lowest_common_ancestor(root.right, p, q)

  # 如果 p 和 q 分别在左子树和右子树中
  return root

代码实现:

class Node:
  def __init__(self, val):
    self.val = val
    self.left = None
    self.right = None

def lowest_common_ancestor(root, p, q):
  if not root:
    return None

  # 如果 p 和 q 都在左子树中
  if root.val > p.val and root.val > q.val:
    return lowest_common_ancestor(root.left, p, q)

  # 如果 p 和 q 都在右子树中
  if root.val < p.val and root.val < q.val:
    return lowest_common_ancestor(root.right, p, q)

  # 如果 p 和 q 分别在左子树和右子树中
  return root

# 测试代码
root = Node(1)
root.left = Node(2)
root.right = Node(3)
root.left.left = Node(4)
root.left.right = Node(5)

p = root.left.left
q = root.left.right

lca = lowest_common_ancestor(root, p, q)
print(lca.val)  # 输出 2

时间复杂度:

算法的时间复杂度为 O(n),其中 n 是二叉树的节点数。这是因为算法需要遍历整个二叉树一次。

空间复杂度:

算法的空间复杂度为 O(h),其中 h 是二叉树的高度。这是因为算法需要使用一个栈来存储递归调用的状态。

总结:

LeetCode 236 题“二叉树的最近公共祖先”是一个经典的算法问题,旨在测试你的解决问题能力和代码实现能力。这道题要求你找出二叉树中两个指定节点的最近公共祖先,即这两个节点的共同祖先中深度最大的一个。本文从问题分析、算法设计和代码实现三个方面详细讲解了这道题的解法,希望对各位程序员和算法爱好者有所帮助。