Appearance
链表
链表题的核心是指针操作与边界处理。先写清函数契约:输入代表什么、返回什么、谁拥有节点、是否允许修改结构;再处理空节点和单节点。
Dummy Node
涉及删除头节点、合并或分段拼接时,使用栈上的 dummy node 可统一边界:
cpp
ListNode dummy{0, head};
ListNode* prev = &dummy;
// 修改 prev->next
return dummy.next;不要为仅作哨兵的节点 new 后忘记释放。在线评测返回的新链表节点是否由调用方释放取决于题目约定;工程代码优先使用 RAII 所有权。
反转链表
迭代法 O(n) 时间、O(1) 额外空间,避免深链表递归导致栈溢出:
cpp
ListNode* reverse(ListNode* head) {
ListNode* previous = nullptr;
while (head) {
ListNode* next = head->next;
head->next = previous;
previous = head;
head = next;
}
return previous;
}反转区间、K 个一组反转的关键是保留区间前驱、区间首节点(反转后变尾)与区间后继,再安全地重新连接。
快慢指针
cpp
while (fast && fast->next) {
slow = slow->next;
fast = fast->next->next;
}常见用途:
- 找中点:奇数长度时
slow落在中点,偶数时落在后半段起点; - 判断环:快慢指针相遇说明有环;
- 找环入口:相遇后,一个指针回到头部,二者同速前进,再次相遇即入口;
- 回文链表:找中点、反转后半段、逐项比较;若题目要求保持原链表,应再反转恢复。
两链表相交
让指针 A 走 A 再走 B,指针 B 走 B 再走 A;相交则在交点相遇,不相交则同时变为 nullptr。它比较的是节点地址而非节点值,时间 O(m+n)、空间 O(1)。