给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。
输入:head = [1,2,3,4,5], left = 2, right = 4
输出:[1,4,3,2,5]
直接思路
找到lefe->right
那一段需要反转的部分,再连接起来. 需要注意的一个细节:因为头节点有可能发生变化,使用虚拟头节点可以避免复杂的分类讨论
(1)设置一个虚拟头指针,令pre、rightNode指针分别到left前一个和right位置
(2)截取链表,将原链表切分成三部分
(3)调用反转链表函数,然后将三段再拼接起来
ListNode* reverseBetween(ListNode* head, int left, int right) {
ListNode* dummyNode = new ListNode(-1);
dummyNode->next = head;
ListNode* pre = dummyNode;
//pre来到left的前一个节点
for(int i = 0; i < left - 1;i++){
pre = pre->next;
}
ListNode* rightNode = pre;
for(int i = 0; i < right - left + 1; i++){
rightNode = rightNode->next;
}
//截取链表
ListNode* leftNode = pre->next;
ListNode* curr = rightNode->next;
//切断连接
pre->next = nullptr;
rightNode->next = nullptr;
pre->next = reverseLists(leftNode);
leftNode->next = curr;
return dummyNode->next;
}
头插法
定义两个指针 pre和cur
cur是当前要反转的指针
pre是第一个要反转数字的前一个位置,保持不变
(1)将pre 移动到第一个要反转的节点的前面,将 cur 移动到第一个要反转的节点的位置上(left位置)。还是以 m=2,n=4为例
(2)将cur后面的元素添加到pre 的后面 [循环体]
(3)退出循环的条件是?
如m=2 n = 4 则有三个数字需要反转,需要2(4-2)次交换
ListNode* reverseBetween(ListNode* head, int left, int right) {
ListNode *dummyNode = new ListNode(-1);
dummyNode->next = head;
ListNode *pre = dummyNode;
for(int i = 0; i < left - 1; i++){
pre = pre->next;
}
ListNode *next = NULL;
ListNode *cur = pre->next;
for(int i = 0; i < right - left; i++){
next = cur->next;
cur->next = next->next;
next->next = pre->next;
pre->next = next;
}
return dummyNode->next;
}