面试题 02.07. 链表相交
给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
图示两个链表在节点 c1 开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
示例 1:
示例 2:
示例 3:
提示:
-
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]
思考:
这道题在理解时有一个陷阱,它并不仅仅是寻找两个链表中数值相同的两个结点,而是寻找一个交点,交点后面的结点都一模一样。既然交点过后一模一样,那就代表着交点后面结点的数值以及长度都是相等的,对于一长一短两个链表,可以先进行预处理,让长链表中结点的指针移动到和短链表尾部对其的位置。
双指针法:
接着就可以比较剩下的子链表是否相同。如果不相同,同时向后移动指针。否则返回空指针。
class Solution {
public:
ListNode* getIntersectionNode(ListNode* headA, ListNode* headB) {
ListNode* curA = headA;
ListNode* curB = headB;
int lenA = 0, lenB = 0;
while (curA != NULL) { // 求链表A的长度
lenA++;
curA = curA->next;
}
while (curB != NULL) { // 求链表B的长度
lenB++;
curB = curB->next;
}
curA = headA; //A链表指针
curB = headB; //B链表指针
// 让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 != NULL) {
if (curA == curB) { //找到公共结点
return curA;
}
curA = curA->next;
curB = curB->next;
}
return NULL;
}
};
代码参考:代码随想录
哈希表:
利用哈希表存储链表的结点,先遍历第一个链表,将第一个链表的每个结点加入到哈希集合中,然后遍历第二个链表,进行判断。
- 如果当前节点不在哈希集合中,则继续遍历下一个节点;
- 如果当前节点在哈希集合中,则后面的节点都在哈希集合中,即从当前节点开始的所有节点都在两个链表的相交部分,因此在链表headB 中遍历到的第一个在哈希集合中的节点就是两个链表相交的节点,返回该节点。
- 如果链表headB中的所有节点都不在哈希集合中,则两个链表不相交,返回null。
class Solution {
public:
//哈希表
ListNode* getIntersectionNode(ListNode* headA, ListNode* headB) {
unordered_set<ListNode*> visited;
ListNode* temp = headA;
while (temp != nullptr) {
visited.insert(temp);
temp = temp->next;
}
temp = headB;
while (temp != nullptr) {
if (visited.count(temp)) {
return temp;
}
temp = temp->next;
}
return nullptr;
}
};
代码参考:力扣官方题解
往期回顾:
LeetCode19. 删除链表的倒数第 N 个结点
LeetCode24. 两两交换链表中的节点
LeetCode206. 反转链表
LeetCode707.设计链表
LeetCode203.移除链表元素
LeetCode54. 螺旋矩阵
LeetCode59.螺旋矩阵II
LeetCode977.有序数组的平方
LeetCode844.比较含退格的字符串
LeetCode283.移动零
LeetCode27.移除元素
LeetCode26.删除有序数组中的重复项
LeetCode209.长度最小的子数组
LeetCode904. 水果成篮
LeetCode242.有效的字母异位词
LeetCode76.最小覆盖子串