关于 链表内指定区间反转 中思路非常多,如果使用拆分链表的方法,那么可以细分考虑虚拟头结点的有无,(这里的虚拟头结点,不是说不存在的,它也是动态开辟的一块内存空间,只是在算法计算中不过多的关联,像哨兵一样,用于站岗!!!!!)
我们以这个例子开始讨论
链表反转
带虚拟头结点
话不多说,上代码
class Solution {
private:
ListNode* reverNode(ListNode* head){
ListNode* sentrynode = new ListNode(0);
sentrynode->next = head;
ListNode* cur = sentrynode->next;
ListNode *pre = nullptr;
while(cur){
ListNode *nxt = cur->next;
cur->next = pre;
pre = cur;
cur = nxt;
}
ListNode *res = sentrynode->next;
delete sentrynode;
return res;
}
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
// write code here
ListNode *sentrynode = new ListNode(0);
sentrynode->next = head;
ListNode* pre = sentrynode;
for(int i =0; i < m-1; ++i){
pre = pre->next;
}
ListNode* leftnode = pre->next; //反转点
ListNode* curinter1 = pre; //切割点
for(int i = 0; i < n-m +1; ++i){
curinter1 = curinter1->next;
}
ListNode* rightnode = curinter1->next; //右衔接点
pre->next = nullptr;
curinter1->next = nullptr;
ListNode* turn = reverNode(leftnode);
pre->next = curinter1;
turn->next = rightnode;
return sentrynode->next;
}
};
此时此刻,在区间反转上,我们返回的res 节点 仍然是head 的位置上的节点
跳出私有成员函数后,完成衔接的各个结果为
不带虚拟头结点
class Solution {
private:
ListNode* reverNode(ListNode* head){
ListNode* cur = head;
ListNode *pre = nullptr;
while(cur){
ListNode *nxt = cur->next;
cur->next = pre;
pre = cur;
cur = nxt;
}
return pre;
}
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
// write code here
ListNode *sentrynode = new ListNode(0);
sentrynode->next = head;
ListNode* pre = sentrynode;
for(int i =0; i < m-1; ++i){
pre = pre->next;
}
ListNode* leftnode = pre->next; //反转点 兼 左衔接点
ListNode* curinter1 = pre; //切割点
for(int i = 0; i < n-m +1; ++i){
curinter1 = curinter1->next;
}
ListNode* rightnode = curinter1->next; //右衔接点
ListNode* remain = leftnode; //左衔接点
pre->next = nullptr;
curinter1->next = nullptr;
ListNode* turn = reverNode(leftnode);
pre->next = turn;
remain->next = rightnode;
ListNode* res = sentrynode->next;
delete sentrynode;
return res;
}
};
不同于带虚拟头结点的方法,在区间反转上,我们返回的私有成员函数里的pre 节点 此时此刻 是 反转前的尾巴了。
在衔接过程,我们需要保留多一份 左衔接点 变量 ,完成衔接后
( 小插曲 ,当然有直接用头插法进行操作 ( 直接在循环里进行链表反转 、交换逻辑相对复杂点) )
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
// write code here
ListNode* sentrynode = new ListNode(0);
sentrynode->next = head;
ListNode* pre = sentrynode;
for(int i = 0; i < m-1; ++i){
pre = pre->next;
}
ListNode* cur = pre->next;
ListNode* nxt = cur->next;
for(int i =0; i < n-m; ++i){
cur->next = nxt->next;
nxt->next = pre->next;
pre->next = nxt;
nxt = cur->next;
}
ListNode* res = sentrynode->next;
delete sentrynode;
return res;
}
};
完结撒花!!!!!!!!!!!!!!