给你单链表的头指针 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]
思路
- 在第一次反转链表的基础上,使用四个指针记录当前遍历的位置(反转前的那个头,反转后的结尾,反转的第一个元素,反转的最后一个元素)。
- 把反转区域反转之后,只需要把反转区域头尾处理一下就行
- 用的三指针做的链表反转(保证一次遍历)
代码:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int left, int right) {
if(head == nullptr) return head;
ListNode* dummyNode = new ListNode(-1); // 虚拟节点,防止处理头部多种情况
dummyNode->next = head;
ListNode* pre = dummyNode;
while(left > 1) {
pre = head;
head = head->next;
left--;
right--;
}
ListNode* prevNode = nullptr;
ListNode* curNode = head;
ListNode* rLeft = head;
ListNode* nextNode = head->next;
while(nextNode && right > 1) {
curNode->next = prevNode;
prevNode = curNode;
curNode = nextNode;
nextNode = nextNode->next;
right--;
}
ListNode* succ = curNode->next;
curNode->next = prevNode;
if(pre) pre->next = curNode;
rLeft->next = succ;
return dummyNode->next;
}
};