反转链表II
给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
示例 1:
输入:head = [1,2,3,4,5], left = 2, right = 4
输出:[1,4,3,2,5]
示例 2:
输入:head = [5], left = 1, right = 1
输出:[5]
其实做完反转链表后,该题的思路并不难想到,重点是如何确定边界条件,以及最后的逻辑处理。
如果没做过反转链表的话,建议先去做做,我有详细题解
1.创建哑节点:为了简化边界条件的处理,创建一个哑节点(dummy node),它的值初始化为0,并且将它的next指针指向头节点head。哑节点不包含在反转的范围内,但可以简化代码逻辑。
2.移动到反转起始位置:使用一个循环,将pre指针移动到反转开始的位置前一个节点(即第m-1个节点)。这样pre就指向了将要反转的子链表的前一个节点,而cur将指向第m个节点,即反转的起始节点。
相信到这里你就感觉很熟悉了,这不就是反转链表的逻辑吗?接下来开始执行反转。
3.执行反转:使用另一个循环,从第m个节点开始,直到第n个节点结束,进行节点的反转操作。在循环中:
(1).保存当前节点cur的下一个节点到nextTemp。
(2).将当前节点cur的next指针指向前一个节点prev,实现反转。
(3).更新prev为当前节点cur,即将当前节点加入到已反转的链表中。
(4).更新cur为nextTemp,即移动到下一个待反转的节点。
4.连接反转后的链表:在完成反转后,需要将反转子链表的尾部连接到原始链表的剩余部分。通过pre->next->next = cur;将反转子链表的最后一个节点的next指针指向原始链表中第n+1个节点。
5.更新哑节点的下一个节点:通过pre->next = prev;将哑节点的下一个节点更新为反转子链表的头节点,即第m个节点。
6.返回结果:最后,返回哑节点的下一个节点dummy->next,即更新后的链表的头节点。
其中较难理解的是第4步和第5步,这里建议读者自己画个图理解一下。
以示例1为例,我们执行完第三步后,反转部分应该为4=>3=>2,但这个部分与原链表还没有联系起来,如下面这个图所示,所以我们要将它们连接起来。
这是pre指向的是开始反转的前一个节点,故是1,然后1节点的next指向的是2,我们要将2的next指向5,所以代码表示为:
pre->next->next = cur;
然后将1的next指向4,所以代码表示为:
pre->next = prev;
最后变成这样
看着难受?把箭头理一下,变成
完整代码如下:
class Solution {
public:
// 函数用于反转链表中从位置m到位置n的节点
ListNode* reverseBetween(ListNode* head, int m, int n) {
// 如果头节点为空,或者链表只有一个节点,或者m和n相等(即不需要反转),则直接返回头节点
if (head == nullptr || head->next == nullptr || m == n) {
return head;
}
// 创建一个哑节点,其next指向头节点head,用于简化链表操作
ListNode* dummy = new ListNode(0);
dummy->next = head;
// pre指针用于指向将要反转的子链表的第一个节点的前一个节点
ListNode* pre = dummy;
// 移动pre指针到第m个节点的前一个节点
for (int i = 1; i < m; ++i) {
pre = pre->next;
}
// cur指针用于遍历需要反转的子链表
ListNode* cur = pre->next;
// prev指针用于指向已反转的子链表的最后一个节点,初始为NULL
ListNode* prev = nullptr;
// 从第m个节点开始,直到第n个节点,进行节点的反转操作
for (int i = m; i <= n; ++i) {
// 保存当前节点的下一个节点
ListNode* nextTemp = cur->next;
// 将当前节点的next指向prev,实现反转
cur->next = prev;
// 更新prev为当前节点,cur移动到下一个节点
prev = cur;
cur = nextTemp;
}
// 将反转后子链表的最后一个节点的next指向原始链表的剩余部分
pre->next->next = cur;
// 更新哑节点的下一个节点为反转后的子链表的第一个节点
pre->next = prev;
// 返回哑节点的下一个节点,即新链表的头节点
return dummy->next;
}
};
做完此题,可以看看
牛客OR152 | 每k个一组反转链表 |
---|