一 翻转链表
1.1 区域翻转链表
cpp
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int left, int right) {
// 1. 创建虚拟头节点 dummy,其 next 指向原链表头节点
// 作用:统一处理 left=1 的边界情况(此时反转起点是原链表头,需要一个前驱节点)
ListNode dummy(0, head); // 示例:dummy -> 1 -> 2 -> 3 -> 4 -> 5
// 2. 定义 p0 指针,初始指向 dummy,用于定位「反转区间的前一个节点」
ListNode* p0 = &dummy;
// 3. 将 p0 移动到「反转区间的前一个节点」(即第 left-1 个节点的位置)
// 循环次数:left-1 次(因为从 dummy 开始,dummy 是第 0 个节点)
// 示例:left=2,循环 1 次后,p0 指向 1(此时 p0->next 是 2,即反转起点)
for (int i = 0; i < left - 1; i++) {
p0 = p0->next;
}
// 4. 初始化反转用的指针:pre 记录前一个节点,cur 记录当前节点
ListNode* pre = nullptr; // 初始为空(反转的第一个节点的前一个是 null)
ListNode* cur = p0->next; // cur 指向反转区间的第一个节点(示例:cur 初始指向 2)
// 5. 反转「left 到 right」之间的节点(共 right-left+1 个节点)
// 每次循环将 cur 节点的 next 指向 pre,完成单个节点的反转
for (int i = 0; i < right - left + 1; i++) {
ListNode* nxt = cur->next; // 先保存 cur 的下一个节点(防止丢失后续链表)
cur->next = pre; // 反转:当前节点指向前一个节点(核心步骤)
pre = cur; // pre 后移:指向当前节点(下一次循环的「前一个节点」)
cur = nxt; // cur 后移:指向之前保存的下一个节点
}
// 循环结束后:
// pre 指向反转区间的最后一个节点(即反转后的新头部,示例:pre=4)
// cur 指向反转区间后的第一个节点(示例:cur=5)
// 6. 连接反转后的链表与原链表的前后部分
// p0->next 是反转前的第一个节点(现在是反转后的最后一个节点,示例:p0->next=2)
// 让其 next 指向 cur(反转区间后的节点,示例:2->5)
p0->next->next = cur;
// 让 p0 的 next 指向 pre(反转后的新头部,示例:1->4)
p0->next = pre;
// 7. 返回虚拟头节点的 next(即反转后的链表头)
return dummy.next;
}
};
【1】dummy node :开始节点的前驱节点,这个节点是new出来的
【2】需要理解指针的含义,即使链表的指针本质上也是相同的
【3】翻转部分就是翻转列表的基础代码
1.2 翻转列表
cpp
class Solution {
public:
ListNode* reverseList(ListNode* head) {
ListNode* prev = nullptr;
ListNode* curr = head;
while(curr){
ListNode* next = curr->next;
curr->next = prev;
prev = curr;
curr = next;
}
return prev;
}
};