20. 相交链表【LC160】

112 阅读2分钟

题目:

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。

图示两个链表在节点 c1 开始相交:

image.png

题目数据 保证 整个链式结构中不存在环。

注意,函数返回结果后,链表必须 保持其原始结构 。

自定义评测:

评测系统 的输入如下(你设计的程序 不适用 此输入):

  • intersectVal - 相交的起始节点的值。如果不存在相交节点,这一值为 0
  • listA - 第一个链表
  • listB - 第二个链表
  • skipA - 在 listA 中(从头节点开始)跳到交叉节点的节点数
  • skipB - 在 listB 中(从头节点开始)跳到交叉节点的节点数 评测系统将根据这些输入创建链式数据结构,并将两个头节点 headA 和 headB 传递给你的程序。如果程序能够正确返回相交节点,那么你的解决方案将被 视作正确答案 。 处。

image.png

image.png

核心思路:

方案1: 利用Map数据结构,分别遍历两个链表来实现。

这里面利用了map的键值可以是一个对象的特点,非常方便。

方案2: AB&BA双指针遍历法

这里面一个关键点,就是,我们考虑的时候一定是基于链表的维度考虑的。 跟同事用两个list考虑一会,甚至觉得可以无限循环。。。哈哈哈,

接下来说一下具体的思路吧:

1)循环就一定需要跳出循环的条件,如果A=B跳出循环;

2)循环要有循环条件,也就是遍历终止的条件, while(A !== B);

3)将两个链表长度拉齐,其实关键点就是比较两个指针后段,两个指针同步幅遍历。明确几个点:

3.1)如果两个链表长度相同,同步幅双指针可以直接找到交叉点;
3.2)如果两个链表长度不同,就把两个链表连接成AB、BA两个等长链表,再进行比较。

这种方法就很取巧,对吧。怎么出来的这种思路呢?尝试着做以下推导:

AB链表有交点 -> AB链表最后段一定相同 ->怎么样让后段对齐呢? -> A连接B, B连接A

解:

# 方案1
var getIntersectionNode = function (headA, headB) {
  if (!headA || !headB) {
    return null
  };
  let mapA = new Map();
  while (headA) {
    mapA.set(headA, headA.val);
    headA = headA.next;
  }
  while (headB) {
    if (mapA.has(headB)) {
      return headB
    }
    headB = headB.next;
  }
  return null
};
# 方案2
var getIntersectionNode = function (headA, headB) {
    if (!headA || !headB) return null
    let A = headA, B = headB;
    while (A !== B) {
        A = A ? A.next : headB;
        B = B ? B.next : headA;
    }
    return A
};

———— 前端、Javascript实现、算法、刷题、leetcode