其他分享
首页 > 其他分享> > leetcode [160. 相交链表](https://leetcode-cn.com/problems/intersection-of-two-linked-lists/)

leetcode [160. 相交链表](https://leetcode-cn.com/problems/intersection-of-two-linked-lists/)

作者:互联网

leetcode 160. 相交链表

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

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

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

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

自定义评测:

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

评测系统将根据这些输入创建链式数据结构,并将两个头节点 headAheadB 传递给你的程序。如果程序能够正确返回相交节点,那么你的解决方案将被 视作正确答案

示例 1:

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

示例 2:

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

示例 3:

输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null
解释:从各自的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。
由于这两个链表不相交,所以 intersectVal 必须为 0,而 skipA 和 skipB 可以是任意值。
这两个链表不相交,因此返回 null 。

提示:

进阶:你能否设计一个时间复杂度 O(m + n) 、仅用 O(1) 内存的解决方案?

Related Topics

哈希表

链表

双指针

思路1:栈

把2个链表放入2个栈中,然后依次出栈比较大小。

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    if(headA==null || headB == null){
        return null;
    }
    Deque<ListNode> stack1 = new LinkedList<>();
    Deque<ListNode> stack2 = new LinkedList<>();
    ListNode p = headA;
    ListNode q = headB;
    while(p!=null){
        stack1.push(p);
        p = p.next;
    }
    while(q!=null){
        stack2.push(q);
        q = q.next;
    }
    ListNode result = null;
    while(!stack1.isEmpty() && !stack2.isEmpty()){
        if(stack1.peek() == stack2.peek()){
            result = stack1.pop();
            stack2.pop();
        }else{
            break;
        }
    }
    return result;
}
 解答成功:
 执行耗时:2 ms,击败了26.41% 的Java用户
 内存消耗:45.7 MB,击败了5.11% 的Java用户

思路2:哈希表

把链表1放入哈希表中,然后遍历链表2,判断是否在哈希表中出现。

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    if(headA==null || headB == null){
        return null;
    }
    HashSet<ListNode> set = new HashSet<ListNode>();
    ListNode p = headA;
    ListNode q = headB;
    while(p!=null){
        set.add(p);
        p = p.next;
    }
    ListNode result = null;
    while(q!=null){
        if(set.contains(q)){
            result = q;
            break;
        }else{
            q = q.next;
        }
    }
    return result;
}
解答成功:
执行耗时:5 ms,击败了24.30% 的Java用户
内存消耗:43.8 MB,击败了41.02% 的Java用户

思路3:双指针

如果是相交链表:

  1. 假设A链表前面有a,公共部分有c个,总共有a+c=m个。

  2. 假设B链表前面有b个,公共部分有c个,总共有b+c=n个。

  3. 使用pA和pB遍历链表,当pA遍历完时,令pA等于headB,继续遍历。同理pB遍历完时,等于headA继续遍历。

  4. 因为这样走到相交节点时,

    1. 当m==n时,也就是a=b时,会直接相遇。

    2. 当m!=n时,pA走过了m+b(a+b+c)个节点,pB走过了n+a(a+b+c)个节点。

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    if(headA==null || headB == null){
        return null;
    }
    ListNode pA = headA;
    ListNode pB = headB;
    while(pA!=pB){
        pA = pA == null ? headB : pA.next;
        pB = pB == null ? headA : pB.next;
    }
    return pA;
}
解答成功:
            执行耗时:1 ms,击败了99.39% 的Java用户
            内存消耗:44.6 MB,击败了5.11% 的Java用户

标签:ListNode,cn,相交,leetcode,链表,headB,null,节点
来源: https://blog.csdn.net/yingmu__/article/details/123310484