92. 反转链表 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]
解题思路:
沿用三指针的反转,判断left和right的位置来决定类型.需要额外两个节点来暂存left节点z)和left节点的前驱(p_z)
- left在左边界且right在右边界,全部反转;
- left在左边界但right不在右边界::左边节点需要指向后续链表的节点,头节点移到最后一个节点;
- left不在左边界但right在右边界::让z节点指向空,p_z指向反转的最后一个节点;
- 均不在边界::前驱节点指向最后一个节点,z指向后续链表节点;
思路图:
代码:
/**
* 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->next == nullptr)
return head;
int count = right - left;
int loop = left - 1;
ListNode *p = head;
ListNode *p_z = p;
while (loop--)
{
p_z = p;
p = p->next;
}
if(p == nullptr || p->next == nullptr)
return head;
ListNode *z = p;
ListNode *s = p->next;
ListNode *tmp = s->next;
while (s != nullptr && count--)
{
s->next = p;
p = s;
s = tmp;
if(s!=nullptr)
tmp = s->next;
}
if (--left != 0 && s != nullptr)
{
z->next = s;
p_z->next = p;
}
else if(left == 0 && s != nullptr)
{
z->next = s;
head = p;
}
else if (left != 0 && s == nullptr)
{
p_z->next = p;
z->next = nullptr;
}
else if (left == 0 && s == nullptr)
{
head = p;
p_z->next = nullptr;
}
return head;
}
};
运行结果:
总结:
用了大量的空间来换取时间,如果left和right不在边界就不需要遍历链表,只需要修改其中一部分.不过这样会有点绕,容易造成死循环.