每日一题——相交链表

76 阅读4分钟

相交链表三种解法详解

今天我来详细讲解"相交链表"的三种解法:暴力法、哈希表法和双指针法。我会从时间复杂度的角度进行深入分析,帮助你理解每种方法的优缺点。

问题描述

给定两个单链表,判断它们是否相交,并返回相交点。如果相交,返回相交节点;如果不相交,返回null。

1. 暴力解法

var getIntersectionNode = function(headA, headB) { 
  let a = headA; 
  while (a !== null){
    let b = headB; 
    while (b !== null){
      if (a === b){
        return a; 
      } else{
        b = b.next; 
      }
    } 
    a = a.next; 
  } 
  return null
}

时间复杂度分析

  • 外层循环:遍历链表A,时间复杂度为O(m),其中m是链表A的长度。
  • 内层循环:对链表A的每个节点,都需要遍历整个链表B,时间复杂度为O(n),其中n是链表B的长度。
  • 总时间复杂度:O(m × n)

优缺点

  • 优点:实现简单直观,空间复杂度为O(1)
  • 缺点:时间复杂度高,当链表很长时(如m=10^4, n=10^4),需要10^8次操作,效率极低

2. 哈希表解法

var getIntersectionNode = function(headA, headB) { 
  const hashMap = new Map(); 
  let a = headA; 
  let b = headB; 
  while (a){
    hashMap.set(a, 1); 
    a = a.next; 
  } 
  while (b){
    if (hashMap.has(b)){
      return b; 
    } 
    b = b.next 
  } 
  return null
}

时间复杂度分析

  • 遍历链表A:将每个节点存入哈希表,时间复杂度为O(m)
  • 遍历链表B:对每个节点查询哈希表,哈希表查询平均时间复杂度为O(1),总时间复杂度为O(n)
  • 总时间复杂度:O(m + n)

优缺点

  • 优点:时间复杂度较低,比暴力法高效得多
  • 缺点:需要额外空间O(m)来存储哈希表

3. 双指针解法

var getIntersectionNode = function(headA, headB) { 
  let a = headA; 
  let b = headB; 
  if (!a || !b){
    return null; 
  } 
  while (a !== b){
    a = a === null ? headB : a.next; 
    b = b === null ? headA : b.next; 
  } 
  return a;
};

时间复杂度分析

  • 双指针遍历:每个指针最多遍历两个链表,总遍历次数为m + n
  • 总时间复杂度:O(m + n)

优缺点

  • 优点:时间复杂度与哈希表法相同,但空间复杂度仅为O(1),是三种方法中空间效率最高的
  • 核心思想:如果两个链表相交,那么它们的相交点到链表末尾的长度是相同的。通过让两个指针分别遍历两个链表,当一个指针到达末尾时,将其指向另一个链表的头节点,这样两个指针最终会在相交点相遇。

三种方法的比较

方法时间复杂度空间复杂度优点缺点
暴力法O(m×n)O(1)实现简单效率低,不适用于长链表
哈希表法O(m+n)O(m)实现简单,效率高需要额外空间
双指针法O(m+n)O(1)时间空间效率都高逻辑较难理解

为什么双指针法是最佳选择?

双指针法之所以是最佳解法,是因为它在时间复杂度与哈希表法相同(O(m+n))的情况下,空间复杂度却低得多(O(1) vs O(m))。在实际应用中,尤其是处理大规模数据时,空间效率尤为重要。

双指针法的原理详解

假设链表A的长度为m,链表B的长度为n,相交点到链表末尾的长度为k。

  • 如果m > n,那么链表A的指针a会比链表B的指针b多走(m-n)步
  • 当a到达链表A末尾时,a指向链表B的头节点
  • 当b到达链表B末尾时,b指向链表A的头节点
  • 此时,a和b到相交点的距离相同,因此它们会同时到达相交点

这个方法的巧妙之处在于,它通过"绕圈"的方式,让两个指针在相交点相遇,而不需要额外的空间。

总结

  • 暴力法:适合理解问题,但实际应用中应避免使用
  • 哈希表法:实现简单,时间效率高,但需要额外空间
  • 双指针法:时间空间效率都最优,是LeetCode 160题的最佳解法

在实际面试中,双指针法是面试官最希望看到的解法,因为它展示了对问题的深入理解和空间效率的考虑。

希望这个详细解析对你有所帮助!在刷题过程中,理解每种解法的优缺点,选择最适合的解决方案,是提升编程能力的关键。