160. 相交链表 LeetCode 热题 HOT 100
目录
- 过程解析
- 1. 初始化指针
- 2. 遍历过程
- 3. 相交节点分析
- 源码
- C++
- C语言
过程解析
1. 初始化指针
- 定义两个指针
pA
和pB
,分别指向链表 A 和链表 B 的头结点。 - 两个指针以步长为 1 向各自链表尾部遍历。
2. 遍历过程
- 当
pA
遍历到链表 A 的尾节点时,走过了a
个节点,将pA
指向链表 B 的头节点继续遍历。 - 当
pB
遍历到链表 B 的尾节点时,走过了b
个节点,将pB
指向链表 A 的头节点继续遍历。
3. 相交节点分析
- 假设两链表在节点
c1
开始相交,公共尾部长度为c
。 - 当
pA
从链表 B 遍历到交点c1
时,总步数为:
pA总步数 = a + (b - c)
- 当
pB
从链表 A 遍历到交点c1
时,总步数为:
pB总步数 = b + (a - c)
- 因为:
a + (b - c) = b + (a - c)
所以当链表有公共尾部(c > 0)时,两个指针会同时到达第一个交点 c1
。
如果链表不相交(c = 0),当移动两个链表长度的最大公倍数次数,两个指针最终会同时到达 NULL
。
源码
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) {// 边界判断:如果任意链表为空,直接返回 nullptrif(headA == nullptr || headB == nullptr) return nullptr;// 使用两个指针 pA 和 pB 遍历链表// pA 指向链表 A 的头节点,pB 指向链表 B 的头节点// 注意:这只是让 pA/pB 指向链表的节点,不会改变 headA/headB 本身ListNode *pA = headA, *pB = headB;// 双指针循环,直到两个指针相遇(找到交点)或都为 nullptr(无交点)while(pA != pB){// 如果 pA 到达链表 A 尾部,则跳到链表 B 头部,否则向后移动pA = (pA == nullptr) ? headB : pA->next;// 如果 pB 到达链表 B 尾部,则跳到链表 A 头部,否则向后移动pB = (pB == nullptr) ? headA : pB->next;}// 循环结束时:// 1. 如果链表相交,pA/pB 指向第一个交点节点// 2. 如果链表不相交,pA/pB 为 nullptrreturn pA;}
};
C语言
/*** Definition for singly-linked list.* struct ListNode {* int val;* struct ListNode *next;* };*/
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {// 边界判断:如果任意链表为空,直接返回 NULLif (headA == NULL || headB == NULL) return NULL;// 定义两个指针,分别指向链表 A 和链表 B 的头节点// 注意:这里是指针赋值,不会改变 headA 和 headB 本身struct ListNode *pA = headA;struct ListNode *pB = headB;// 双指针遍历循环// 当两个指针不相等时,继续循环// 循环会在两指针相遇(相交节点)或都为 NULL(无交点)时退出while (pA != pB) {// 指针 pA 向后移动一步// 如果到达链表尾部,跳到链表 B 的头节点继续遍历pA = (pA == NULL) ? headB : pA->next;// 指针 pB 向后移动一步// 如果到达链表尾部,跳到链表 A 的头节点继续遍历pB = (pB == NULL) ? headA : pB->next;}// 循环结束:// 1. 如果链表相交,pA/pB 指向第一个交点节点// 2. 如果链表不相交,pA/pB 为 NULLreturn pA;
}