Q13-code160- 相交链表

20 阅读1分钟

实现思路

方法1 双指针

1 考虑到A和B的链表长度可能不同,所以如果依次移动pa和pb,那么就永远无法【同时】指向相交对象

2 假设A的链表长度m = a + c; B的链表长度 n= b + c

  • 其中 c是 A和B的相交节点的长度
  • 当 a !== b时,一开始依次移动 pa和pb,肯定无法指向 同一个相交对象t
  • 这时候可以在pa遍历完A链表后,继续从B链表的头节点开始,依次向下移动
  • 同理,pb遍历完B链表后,继续从A链表的头节点开始,依次向下移动
  • 就这样每次都依次移动pa和pb,那么在pa移动 a+c+b次后,此时pb必然移动的是 b+c+a次
  • 此时 pa的值必然等于pb,此时也是相加链表的头节点,从而命中了pa === pb

方法2 Set记录法

1 就是直观的 遍历A链表并记录,然后再B链表里遍历查询有无相同节点

参考文档

1.1- 双指针图解1

1.2- 双指针图解2

代码实现

方法1: 双指针 时间复杂度: O(m+n) 空间复杂度: O(1)

function getIntersectionNode(headA: ListNode | null, headB: ListNode | null): ListNode | null {
 let pa = headA, pb = headB
  while (pa || pb) {
    if (pa === pb) return pa
    pa = pa ? pa.next : headB
    pb = pb ? pb.next : headA
  }
  return pa
};

方法2: Set记录法 时间复杂度: O(m+n) 空间复杂度: O(m)

function getIntersectionNode(headA: ListNode | null, headB: ListNode | null): ListNode | null {
  let seen = new Set();
  for (let pa = headA; pa; pa = pa.next) {
    if (pa) seen.add(pa);
  }
  for (let pb = headB; pb; pb = pb.next) {
    if (seen.has(pb)) return pb;
  }
  return null;
};