返回

30分钟带你通关链表系列全题型解析,刷完环形链表,轻松面试

闲谈

掌握链表系列题型,解锁编程面试难题

环形链表的奥秘

链表是数据结构家族中的一员,以其灵活性而著称。链表的问题广泛存在于编程面试中,其中环形链表脱颖而出。环形链表的独特之处在于,它存在一个闭环,即某个节点指向链表中的另一个节点,形成一个环路。

识别环形链表的关键在于速度:使用快慢指针法。想象一下,一只兔子(快指针)和一只乌龟(慢指针)在链表中赛跑。兔子每次跳两步,而乌龟每次只挪动一步。如果存在环,兔子最终会追上乌龟,这表明链表中有环。

代码示例:

def has_cycle(head):
  slow = head
  fast = head
  while fast and fast.next:
    slow = slow.next
    fast = fast.next.next
    if slow == fast:
      return True
  return False

反转链表的技巧

反转链表的目标是将链表中的节点顺序反转。实现这一目标的方法有多种,但最常见的两种是迭代法和递归法。

迭代法就像一个从后往前走的舞伴,不断地重新链接节点。它从头部开始,依次将每个节点的前驱指向它自己,一步步地反转链表。

递归法就像一个不断交换左右手的魔术师。它将链表分为两部分,递归地反转第二部分,然后将反转后的第二部分作为第一部分的下一个节点。

代码示例(迭代法):

def reverse_list(head):
  prev = None
  curr = head
  while curr:
    next = curr.next
    curr.next = prev
    prev = curr
    curr = next
  return prev

代码示例(递归法):

def reverse_list(head):
  if not head or not head.next:
    return head
  p = reverse_list(head.next)
  head.next.next = head
  head.next = None
  return p

链表排序的艺术

链表排序就像烹饪一道美味的菜肴,需要恰当的算法来调和链表中的节点。归并排序、快速排序和插入排序等算法都是链表排序的得力助手。

归并排序的思路是:分而治之。它将链表分成两部分,递归地对这两部分进行排序,然后将排序后的两部分合并成一个有序的链表。

代码示例(归并排序):

def merge_sort(head):
  if not head or not head.next:
    return head

  mid = find_middle(head)
  right = split(mid.next)
  mid.next = None

  left = merge_sort(head)
  right = merge_sort(right)

  return merge(left, right)

def find_middle(head):
  slow = head
  fast = head.next
  while fast and fast.next:
    slow = slow.next
    fast = fast.next.next
  return slow

def split(head):
  curr = head
  prev = None
  while curr:
    prev = curr
    curr = curr.next
  prev.next = None
  return head

def merge(left, right):
  dummy = ListNode(0)
  curr = dummy
  while left and right:
    if left.val < right.val:
      curr.next = left
      left = left.next
    else:
      curr.next = right
      right = right.next
    curr = curr.next

  if left:
    curr.next = left
  if right:
    curr.next = right

  return dummy.next

合并链表的融合

合并链表就像拼拼图,将两个或多个链表的碎片拼凑成一个完整的链表。迭代法和递归法再次成为我们的帮手。

迭代法就像一个精明的园丁,逐步地将两个链表的节点融合在一起。它从两个链表的头部开始,逐个比较它们的节点,将较小的节点添加到结果链表中。

递归法就像一个神奇的变魔术师,将两个链表的节点按顺序依次变出来,最后将它们拼接成一个链表。

代码示例(迭代法):

def merge_two_lists(l1, l2):
  dummy = ListNode(0)
  curr = dummy
  while l1 and l2:
    if l1.val < l2.val:
      curr.next = l1
      l1 = l1.next
    else:
      curr.next = l2
      l2 = l2.next
    curr = curr.next

  if l1:
    curr.next = l1
  if l2:
    curr.next = l2

  return dummy.next

结论:

掌握链表系列题型是编程面试中的必备技能。理解环形链表、反转链表、链表排序和合并链表的原理和实现方法至关重要。通过深入探索这些问题,你可以提升自己的算法技能,为面试中的挑战做好充分准备。

常见问题解答:

  1. 环形链表的判断有哪些其他方法?
  • 弗洛伊德环检测法
  1. 反转链表是否有更简洁的方法?
  • 使用栈或队列
  1. 链表排序是否有其他高效的算法?
  • 堆排序
  1. 合并链表时,两个链表的长度是否必须相等?
  • 不需要
  1. 链表中如何高效地查找中间节点?
  • 使用快慢指针法