返回

剑指 Offer(专项突击版):第 15 | 16 题精解

前端

前言

随着前端技术的发展,面试中算法题的考察越来越常见。为了帮助你做好充分的准备,我们特别推出《剑指 Offer(专项突击版)》系列文章,旨在逐题解析该书中的算法题,助你轻松应对面试挑战。

第 15 题:二叉树的最近公共祖先

题目

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

示例:

     1
   /   \
  2     3
 / \   / \
4   5 6   7

对于节点 4 和 5,最近公共祖先是节点 2。

对于节点 4 和 6,最近公共祖先是节点 1。

解题思路

最近公共祖先问题可以通过递归的方式解决。对于给定的两个节点,我们可以分别找到它们在树中的路径,然后从根节点开始,逐层比较两条路径上的节点。第一个不同的节点就是这两个节点的最近公共祖先。

代码实现

def lowest_common_ancestor(root, p, q):
  """
  Finds the lowest common ancestor of two nodes in a binary tree.

  Args:
    root: The root node of the binary tree.
    p: The first node.
    q: The second node.

  Returns:
    The lowest common ancestor of the two nodes.
  """

  if root is None:
    return None

  if root == p or root == q:
    return root

  left = lowest_common_ancestor(root.left, p, q)
  right = lowest_common_ancestor(root.right, p, q)

  if left and right:
    return root

  return left or right

第 16 题:合并两个排序链表

题目

合并两个排序链表,使合并后的链表依然有序。

示例:

链表 11->2->4

链表 21->3->4

合并后的链表:1->1->2->3->4->4

解题思路

合并两个排序链表可以通过迭代的方式解决。我们首先创建一个新的链表,然后从两个链表中依次取出最小的节点,将其添加到新的链表中。当其中一个链表为空时,我们将另一个链表剩下的节点全部添加到新的链表中。

代码实现

def merge_two_sorted_lists(l1, l2):
  """
  Merges two sorted linked lists into one sorted linked list.

  Args:
    l1: The first sorted linked list.
    l2: The second sorted linked list.

  Returns:
    The merged sorted linked list.
  """

  dummy = ListNode(0)
  current = dummy

  while l1 and l2:
    if l1.val < l2.val:
      current.next = l1
      l1 = l1.next
    else:
      current.next = l2
      l2 = l2.next

    current = current.next

  if l1:
    current.next = l1

  if l2:
    current.next = l2

  return dummy.next

结语

通过对《剑指 Offer(专项突击版)》第 15 和第 16 题的深入解析,相信你对二叉树的最近公共祖先和合并两个排序链表这两个问题有了更深刻的理解。掌握这些算法技能,不仅可以帮助你提高编程能力,也能让你在面试中脱颖而出。

希望《剑指 Offer(专项突击版)》系列文章能够成为你算法学习的得力助手,祝你在算法之路上越走越远!