描述
将一个节点数为 size 链表 m 位置到 n 位置之间的区间反转,要求时间复杂度 �(�)O(n),空间复杂度 �(1)O(1)。
例如:
给出的链表为 1→2→3→4→5→NULL, m=2,n=4,
返回 1→4→3→2→5→NULL.
数据范围: 链表长度 0<size≤1000,0<m≤n≤size,链表中每个节点的值都满足∣val∣≤1000
要求:时间复杂度O(n) ,空间复杂度O(n)
C语言实现
首先找到m位置的前一个节点和m所在节点,分别用两个指针指向。
第二步就是设立尾部节点的指针,防止最终尾部节点丢失与前后关联不上。
第三步就是单链表完全反转,这里如果有不太懂的可以去看我上一篇写的有关反转链表的部分,
最后就是将反转后的部分的头部与m的前一个节点相连,这里要注意如果前一个节点为空即m为head节点则直接让head = pPre。
struct ListNode* reverseBetween(struct ListNode* head, int m, int n ) {
// write code here
if(head == NULL || head->next ==NULL)
return head;
struct ListNode* q = NULL,*p = head;
for(int i = 0; i < m - 1; i++) {
q = p;
p = p->next;
}
//此时p指向第m个节点,q指向m前一个节点
struct ListNode* end = p;//end用来指向逆序后的尾节点
struct ListNode* pPre = p,*nxt = NULL;
p = p->next;
//我发现单链表逆序还真是都要用三个节点去指,nxt用以指向下一个节点,p节点拿来逆序,pPre拿来指向前一个节点
for(int i = m + 1; i <= n; ++i){
nxt = p->next;
p->next = pPre;
pPre = p;
p = nxt;
}
end->next = p;//此时的p节点指向的是第n + 1个节点
if(q){//注意q节点可能为空
q->next = pPre;
}else{
head = pPre;
}
return head;
}
C++
ListNode* reverseBetween(ListNode* head, int m, int n) {
if(head == nullptr || head->next == nullptr)
return head;
ListNode* q = nullptr,*p = head;
for(int i = 0; i < m - 1; i++) {
q = p;
p = p->next;
}
//此时p指向第m个节点,q指向m前一个节点
ListNode* end = p;//end用来指向逆序后的尾节点
ListNode* pPre = p,*next = nullptr;
p = p->next;
for(int i = m + 1; i <= n; ++i){
next = p->next;
p->next = pPre;
pPre = p;
p = next;
}
end->next = p;//此时的p节点指向的是第n + 1个节点
if(q){//注意q节点可能为空
q->next = pPre;
}else{
head = pPre;
}
return head;
// write code here
}
最后,写文不易,不收藏也请给个赞,谢谢亲~!
(本文仅供学习时参考,如有错误,纯属作者技术不到位,不足之处请多指教,谢谢)