题目链接: 力扣
题目描述
给两个单链表的头节点 headA 和 headB ,找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
题目数据 保证 整个链式结构中不存在环。
函数返回结果后,链表必须 保持其原始结构 。
题目分析
两链表是相交,不是交叉,因而只要找到相交的起始结点,之后的结点都认为是相交的。
如下图所示,相交的起始结点认为是c1
代码实现
解题思路1:哈希集合
用哈希集合存储链表A节点,若集合中存在链表B的节点说明相交。
解题思路2:双指针
两链表都不为空时,创建两个指针 pA和 pB,初始时分别指向两个链表的头节点 headA 和 headB,然后将两个指针依次遍历两个链表的每个节点。
每步操作需要同时更新指针 pA 和 pB。
如果指针pA 不为空,则将指针移到下一个节点;如果指针 pB 不为空,则将指针移到下一个节点。
如果指针pA 为空,则将指针移到链表 headB 的头节点;如果指针 pB 为空,则将指针移到链表headA 的头节点。
当指针 pA 和 pB 指向同一个节点或者都为空时,返回它们指向的节点或者 null。
/**
* hash集合
*
* 时间复杂度:O(m+n),m 和 n 分别指链表 headA 和 headB 的长度
* 空间复杂度:O(m)
*
* @param headA
* @param headB
* @return
*/
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
Set<ListNode> set = new HashSet<ListNode>();
ListNode temp = headA;
// headA放入集合
while (temp != null){
set.add(temp);
temp = temp.next;
}
temp = headB;
while (temp != null){
if(set.contains(temp)){
return temp;
}
temp = temp.next;
}
return null;
}
/**
* 双指针
*
* 时间复杂度:O(m+n),m 和 n 分别指链表 headA 和 headB 的长度
* 空间复杂度:O(1)
*
* @param headA
* @param headB
* @return
*/
public ListNode getIntersectionNode2(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;
}