leetcode [160. 相交链表](https://leetcode-cn.com/problems/intersection-of-two-linked-lists/)
作者:互联网
leetcode 160. 相交链表
给你两个单链表的头节点 headA
和 headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null
。
图示两个链表在节点 c1
开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
自定义评测:
评测系统 的输入如下(你设计的程序 不适用 此输入):
-
intersectVal
- 相交的起始节点的值。如果不存在相交节点,这一值为0
-
listA
- 第一个链表 -
listB
- 第二个链表 -
skipA
- 在listA
中(从头节点开始)跳到交叉节点的节点数 -
skipB
- 在listB
中(从头节点开始)跳到交叉节点的节点数
评测系统将根据这些输入创建链式数据结构,并将两个头节点 headA
和 headB
传递给你的程序。如果程序能够正确返回相交节点,那么你的解决方案将被 视作正确答案 。
示例 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 。
提示:
-
listA
中节点数目为m
-
listB
中节点数目为n
-
1 <= m, n <= 3 * 104
-
1 <= Node.val <= 105
-
0 <= skipA <= m
-
0 <= skipB <= n
-
如果
listA
和listB
没有交点,intersectVal
为0
-
如果
listA
和listB
有交点,intersectVal == listA[skipA] == listB[skipB]
进阶:你能否设计一个时间复杂度 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:双指针
如果是相交链表:
-
假设A链表前面有a,公共部分有c个,总共有a+c=m个。
-
假设B链表前面有b个,公共部分有c个,总共有b+c=n个。
-
使用pA和pB遍历链表,当pA遍历完时,令pA等于headB,继续遍历。同理pB遍历完时,等于headA继续遍历。
-
因为这样走到相交节点时,
-
当m==n时,也就是a=b时,会直接相遇。
-
当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