返回

LeetCode算法精粹:轻松掌握「合并两个有序链表」难题,实现强强联合!

见解分享

LeetCode算法精粹:轻松掌握「合并两个有序链表」难题,实现强强联合!

在计算机科学的世界里,算法是解决问题的关键,而LeetCode作为算法学习的殿堂,汇聚了大量精彩的算法难题,等待着我们去征服。今天,我们就来深入探讨LeetCode每日一题「合并两个有序链表」,带你领略算法之美,提升编程实力。

题目:合并两个有序链表

给定两个有序链表head1和head2,合并这两个链表,并返回合并后的排序链表。

思考:

  1. 如何判断两个链表是否已经合并完成?
  2. 如何确定合并后链表的顺序?
  3. 如何处理特殊情况,例如其中一个链表为空的情况?

实现:

  1. 首先,创建一个新的链表head,它将作为合并后链表的头节点。
  2. 然后,分别设置两个指针p1和p2,分别指向head1和head2的头节点。
  3. 循环比较p1和p2指向的节点的值,将较小的节点添加到新链表中,并移动相应的指针。
  4. 当其中一个指针到达链表的末尾时,将另一个链表的剩余节点全部添加到新链表中。
  5. 最后,返回合并后的链表head。

代码:

def merge_two_sorted_lists(head1, head2):
  """
  合并两个有序链表

  Args:
    head1 (ListNode): 第一个链表的头节点
    head2 (ListNode): 第二个链表的头节点

  Returns:
    ListNode: 合并后的链表的头节点
  """

  # 创建一个新的链表head,它将作为合并后链表的头节点
  head = ListNode(0)

  # 设置两个指针p1和p2,分别指向head1和head2的头节点
  p1 = head1
  p2 = head2

  # 循环比较p1和p2指向的节点的值,将较小的节点添加到新链表中,并移动相应的指针
  while p1 and p2:
    if p1.val < p2.val:
      head.next = p1
      p1 = p1.next
    else:
      head.next = p2
      p2 = p2.next

    # 将head指针移动到新添加的节点
    head = head.next

  # 当其中一个指针到达链表的末尾时,将另一个链表的剩余节点全部添加到新链表中
  if p1:
    head.next = p1
  if p2:
    head.next = p2

  # 返回合并后的链表head
  return head

实例:

给定两个有序链表head1和head2,其中:

head1 = 1 -> 2 -> 4 -> null
head2 = 1 -> 3 -> 4 -> null

合并后的链表为:

1 -> 1 -> 2 -> 3 -> 4 -> 4 -> null

优化:

为了进一步优化算法的性能,我们可以使用尾插法来合并两个链表。尾插法是指将新节点添加到链表的末尾,而不是头节点之后。这样可以避免每次添加节点时都需要移动所有节点的指针,从而提高了算法的效率。

代码:

def merge_two_sorted_lists_tail_insertion(head1, head2):
  """
  使用尾插法合并两个有序链表

  Args:
    head1 (ListNode): 第一个链表的头节点
    head2 (ListNode): 第二个链表的头节点

  Returns:
    ListNode: 合并后的链表的头节点
  """

  # 创建一个新的链表head,它将作为合并后链表的头节点
  head = ListNode(0)

  # 设置一个指针tail,它将指向合并后链表的最后一个节点
  tail = head

  # 循环比较p1和p2指向的节点的值,将较小的节点添加到新链表中,并移动相应的指针
  while p1 and p2:
    if p1.val < p2.val:
      tail.next = p1
      p1 = p1.next
    else:
      tail.next = p2
      p2 = p2.next

    # 将tail指针移动到新添加的节点
    tail = tail.next

  # 当其中一个指针到达链表的末尾时,将另一个链表的剩余节点全部添加到新链表中
  if p1:
    tail.next = p1
  if p2:
    tail.next = p2

  # 返回合并后的链表head
  return head

时间复杂度:

合并两个有序链表的算法的时间复杂度为O(n + m),其中n和m分别是两个链表的长度。这是因为算法需要遍历两个链表,并将较小的节点添加到新链表中。

空间复杂度:

合并两个有序链表的算法的空间复杂度为O(1),因为算法不需要额外的空间来存储数据。

LeetCode每日一题「合并两个有序链表」的精妙之处在于,它不仅考察了我们对链表操作的基本功,还要求我们能够灵活运用算法思想,选择最优的解决方案。通过对这道题目的深入剖析,我们不仅掌握了合并两个有序链表的算法,还提升了算法思维能力,为解决更多复杂算法问题打下了坚实的基础。