题目描述
给你两个单链表的头节点 headA
和 headB
,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null
。
图示两个链表在节点 c1
开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
提示:
listA
中节点数目为m
listB
中节点数目为n
0 <= m, n <= 3 * 104
1 <= Node.val <= 105
0 <= skipA <= m
0 <= skipB <= n
- 如果
listA
和listB
没有交点,intersectVal
为0
- 如果
listA
和listB
有交点,intersectVal == listA[skipA + 1] == listB[skipB + 1]
进阶:你能否设计一个时间复杂度 O(n)
、仅用 O(1)
内存的解决方案?
思路
题目要求求两个链表交点节点的指针。 这里要注意,交点不是数值相等,而是指针相等。
首先要求出两个链表的长度,并求出两个链表长度的差值,然后让curA移动到,和curB末尾对齐的位置。此时我们就可以比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到交点。否则循环退出返回空指针。
代码
C++版:
正确的解法:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
// 双指针法
ListNode* curA=headA;
ListNode* curB=headB;
int lenA=0,lenB=0;
// 首先需要分别求出两链表的长度
while(curA!=nullptr){
lenA++;
curA=curA->next;
}
while(curB!=nullptr){
lenB++;
curB=curB->next;
}
curA = headA;
curB = headB;
// 让curA为最长链表的头,lenA为其长度
if (lenB > lenA) {
swap (lenA, lenB);
swap (curA, curB);
}
// 求长度差
int gap=lenA-lenB;
// 让curA和curB在同一起点上(末尾位置对齐)
while (gap--) {
curA = curA->next;
}
// 遍历curA 和 curB,遇到相同则直接返回
while (curA != nullptr) {
if (curA == curB) {
return curA;
}
curA = curA->next;
curB = curB->next;
}
return nullptr;
}
};
错误的解法:忽略了A和B链表在相交之前已有元素相同的情况。
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
// 双指针法
// 当curA和curB其中一个到达nullptr时,则另一个所在的位置可能是两个链表的相交节点
ListNode* curA=headA;
ListNode* curB=headB;
ListNode* result;
while(curA!=nullptr && curB!=nullptr){
curA=curA->next;
curB=curB->next;
}
// 判断是否为相交节点
if(curB==nullptr){
curB=headB;
while(curB!=nullptr && curB!=curA ){
curB=curB->next;
}
if(curB==nullptr){
result=nullptr;
}else{
result=curA;
}
}
if(curA==nullptr){
curA=headA;
while(curA!=nullptr && curB!=curA ){
curA=curA->next;
}
if(curA==nullptr){
result=nullptr;
}else{
result=curB;
}
}
return result;
}
};
Python版:
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
curA=headA
curB=headB
lenA, lenB = 0, 0
while curA: # 求链表A的长度
lenA += 1
curA = curA.next
while curB: # 求链表B的长度
lenB += 1
curB = curB.next
curA, curB = headA, headB
if lenB > lenA:
curA, curB = curB, curA
lenA, lenB = lenB, lenA
for _ in range(lenA - lenB): # 让curA和curB在同一起点上(末尾位置对齐)
curA = curA.next
while curA: # 遍历curA 和 curB,遇到相同则直接返回
if curA == curB:
return curA
else:
curA = curA.next
curB = curB.next
return None