【链表】LeetCode160. 相交链表

115 阅读2分钟

题目

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

示例

160_example_1.png

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at '8'
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A[4,1,8,4,5],链表 B[5,0,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。

差值解法

主要思路

  1. 首先分别去遍历两个链表,并且计算出链表的长度
  2. 然后计算出两个链表的差值的绝对值
  3. 让长的链表先走差值的步数,这样两个链表剩余的节点数量就是一样的了
  4. 最后遍历两个链表剩余的节点,判断是否相交

代码实现

 public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if(headA == null || headB == null){
            return null;
        }
       int a = 0;
       int b = 0;
       ListNode pa = headA;
       ListNode pb = headB;
       while(pa != null && ++a > 0){
           pa = pa.next;
       }
       while(pb != null && ++b >0){
           pb = pb.next;
       }
       int abs = Math.abs(a - b);
       while(abs-- >0){
           if(a > b){
               headA = headA.next;
           }else{
               headB = headB.next;
           }
       }
       while(headA != null && headB != null){
           if(headA == headB){
               return headA;
           }else{
               headA = headA.next;
               headB = headB.next;
           }
       }
       return null;
    }

双指针解法

主要思路

  1. 如果两个链表相交,那么从相交的第一个节点到末尾节点的节点数量在两个链表中都是一样的
  2. 也就是说我们想办法将两个链表的长度变成一样,然后利用两个指针分别遍历
  3. 最终都会找到相交的第一个节点,如果链表不想交,那就找到null节点
  4. 将链表headA变成headA+headB,然后将链表headB+headA

代码实现

    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if(headA == null || headB == null){
            return null;
        }
        ListNode ha = headA;
        ListNode hb = headB;
        while(ha != hb){
        //当ha == null时,ha.next = headB
            ha = ha == null? headB : ha.next;
            hb = hb == null? headA : hb.next;
        }
        return ha;
    }