一. 递归
1. 参考这个作者写的太好了,包括解决反转链表的所有思路.
作者:labuladong
链接:https://leetcode-cn.com/problems/reverse-linked-list-ii/solution/bu-bu-chai-jie-ru-he-di-gui-di-fan-zhuan-lian-biao/
2. 这题是反转m到n区间的链表,如果将head移动到m=1的位置,则变成反转前n-m+1个节点,所以关键是把这个递归写好.
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
//记录第一个节点反转后应该连接哪个节点,
//因为此时的节点反转后不一定指向NULL了
ListNode* post = NULL;
ListNode* reverseN(ListNode* head, int n) {
//如果n==1,说明不需要反转,此时直接返回head,
//并且记录反转后应该连接哪个节点.
if(n==1) {
post = head->next;
return head;
}
//对于head->next来说,只需要反转前n-1个节点就够了.
ListNode* last = reverseN(head->next, n-1);
head->next->next = head;
//让反转后的head和应该连接的之后的点相连接.
head->next = post;
//返回反转后的头结点.
return last;
}
ListNode* reverseBetween(ListNode* head, int m, int n) {
//如果m=1, 说明就和反转前n个节点没有区别了.
if(m==1) return reverseN(head, n);
//head需要连接以head->next为节点,m-1和n-1为区间的节点.
head->next = reverseBetween(head->next,m-1,n-1);
return head;
}
};
二. 迭代
1. 迭代一般思路都很直接.
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
ListNode* dummy = new ListNode(0);
dummy->next = head;
//pre找到m节点的前一个,作为连接点.
ListNode* pre = dummy;
for(int i=0;i<m-1;i++) {
pre = pre->next;
}
ListNode* cur = pre->next;
ListNode* post = NULL;
ListNode* tmp = cur;
//将m到n的区间进行反转.
for(int i=0;i<n-m+1;i++) {
ListNode* next = cur->next;
cur->next = post;
post = cur;
cur = next;
}
//最后连接前面和和后面的链表.
pre->next = post;
tmp->next = cur;
return dummy->next;
}
};