160. 相交链表

371 阅读2分钟

题目介绍

力扣160题:leetcode-cn.com/problems/in…

image.png

image.png

方法一:哈希存储法

判断两个链表是否相交,可以使用哈希集合存储链表节点。

首先遍历链表 headA,并将链表headA 中的每个节点加入哈希集合中。然后遍历链表 headB,对于遍历到的每个节点,判断该节点是否在哈希集合中:

如果当前节点不在哈希集合中,则继续遍历下一个节点;

如果当前节点在哈希集合中,则后面的节点都在哈希集合中,即从当前节点开始的所有节点都在两个链表的相交部分,因此在链表 headB 中遍历到的第一个在哈希集合中的节点就是两个链表相交的节点,返回该节点。

如果链表 headB 中的所有节点都不在哈希集合中,则两个链表不相交,返回 null

代码如下:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) {
 *         val = x;
 *         next = null;
 *     }
 * }
 */
public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if(headA == null || headB == null) {
            return null;
        }

        Map<ListNode,Integer> dataMap = new HashMap<>();
        ListNode tempA = headA;
        while(tempA != null) {
            dataMap.put(tempA,1);
            tempA = tempA.next;
        }
        ListNode tempB = headB;
        while(tempB != null) {
            if(dataMap.containsKey(tempB)) {
                return tempB;
            }          
            tempB = tempB.next;
        }   
        return null;
    }
}

复杂度分析

  • 时间复杂度: O(m+n),其中 m 和 n 是分别是链表 headA 和 headB 的长度。需要遍历两个链表各一次。

  • 空间复杂度: O(m),其中 m 是链表 headA 的长度。需要使用哈希集合存储链表 headA 中的全部节点。

方法二:双指针

根据题目意思,如果两个链表相交,那么相交点之后的长度是相同的

我们需要做的事情是,让两个链表从同距离末尾同等距离的位置开始遍历。这个位置只能是较短链表的头结点位置。为此,我们必须消除两个链表的长度差

  • 指针 pA 指向 A 链表,指针 pB 指向 B 链表,依次往后遍历
  • 如果 pA 到了末尾,则 pA = headB 继续遍历
  • 如果 pB 到了末尾,则 pB = headA 继续遍历
  • 比较长的链表指针指向较短链表head时,长度差就消除了,如此,只需要将最短链表遍历两次即可找到位置

听着可能有点绕,看图最直观,链表的题目最适合看图了

总结:就是两个指针走过的路程肯定是一样的

image.png

image.png

image.png

代码如下:

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    if (headA == null || headB == null) return null;
    ListNode pA = headA, pB = headB;
    while (pA != pB) {
        pA = pA == null ? headB : pA.next;
        pB = pB == null ? headA : pB.next;
    }
    return pA;
}