链表经典算法实战
一、相交链表问题
问题描述
给定两个单链表,判断它们是否相交。若相交,返回相交的节点。注意,判断依据是节点地址是否相同,而非节点值(因为节点值可能存在重复)。
解题思路分析
暴力遍历法
- 方法:遍历链表 A,对于 A 中的每一个节点,再遍历整个链表 B,检查是否存在地址相同的节点。
- 复杂度:时间 O(M*N),空间 O(1)。
- 评价:效率低,长链表场景下不推荐。
双指针对齐法(最优解)
- 方法:
- 分别遍历两个链表,计算各自长度。
- 求出两链表长度差
gap。 - 让较长链表的指针先移动
gap步,使剩余长度一致。 - 两个指针同时移动,逐个比较节点地址,第一个相同的即为交点。
- 复杂度:时间 O(M + N),空间 O(1)。
- 优势:逻辑清晰,效率高,适用于任意长度的链表。
实际开发中,我们优先选择双指针对齐法。
struct ListNode* getIntersectionNode(struct ListNode* headA, struct ListNode* headB) {
struct ListNode* curA = headA, *curB = headB;
int lenA = 1, lenB = 1;
// 计算链表 A 长度
while (curA->next) {
curA = curA->next;
lenA++;
}
// 计算链表 B 长度
while (curB->next) {
curB = curB->next;
lenB++;
}
int gap = abs(lenA - lenB);
struct ListNode* longList = headA;
struct ListNode* shortList = headB;
// 确保 longList 指向较长的链表
if (lenA < lenB) {
longList = headB;
shortList = headA;
}
// 长链表指针先走 gap 步
while (gap--) {
longList = longList->next;
}
(longList) {
(longList == shortList)
longList;
longList = longList->next;
shortList = shortList->next;
}
;
}


