题目描述:
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明:
1 ≤ m ≤ n ≤ 链表长度。
示例:
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
思路:
首先我们考虑到的情况是,反转整个链表该怎样实现。
比较经典的解法是递归反转,代码简洁但需要仔细理解下:
struct ListNode {
int val;
struct ListNode *next;
};
//递归反转整个链表
struct ListNode* reverse(struct ListNode* head) {
if (head->next == null) return head;
struct ListNode* last = reverse(head->next);
head->next->next = head;//将下一个节点变成当前节点的前驱节点
head->next = null;
return last;
}
下面是不用递归,而是用迭代法实现对链表的逆序。
typedef struct ListNode {
int val;
struct ListNode *next;
}ListNode;
ListNode reverseList(ListNode head)
{
ListNode pre = NULL;
while(head != NULL)
{
ListNode cur = head;
head = head->next;
cur->next = pre;
pre = cur;
}
return pre;
}
接下来我们来考虑反转前N个节点又该如何解决:
//反转前N个节点
struct ListNode* successor = null; // 用来记录第n个节点的后驱节点
// 反转以 head 为起点的 n 个节点,返回新的头结点
struct ListNode* reverseN(struct ListNode* head, int n) {
if (n == 1) {
// 记录第 n + 1 个节点
successor = head->next;
return head;
}
// 以 head->next 为起点,需要反转前 n - 1 个节点
struct ListNode* last = reverseN(head->next, n - 1);
head->next->next = head;
// 将反转之后的 head 节点与后面的第n+1节点连起来
head.next = successor;
return last;
}
此时,对于反转链表的一段我们则可以考虑将其分解为:
当其实点m为1时,即为反转前n个节点;
当m不等于1时,则递归的看作是反转head->next 的[m-1,n-1] 的节点;对于head->next->next 则是反转[m-2,n-2]的节点;递归下去。代码如下:
//反转一部分
struct ListNode* reverseBetween(struct ListNode* head, int m, int n) {
// base case
if (m == 1) {//相当于反转前n个元素
return reverseN(head, n);
}
// 前进到反转的起点触发 base case
head-.next = reverseBetween(head->next, m - 1, n - 1);
return head;
}
题目的完整ac代码如下:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* struct ListNode *next;
* };
*/
struct ListNode* successor = NULL; //存放后驱节点
struct ListNode* reverseN(struct ListNode* head, int n){
if(n==1){
successor = head->next;
return head;
}
struct ListNode* last = reverseN(head->next, n-1);
head->next->next = head;//将下一个节点变成当前节点的前驱节点
head->next = successor;
return last;
}
struct ListNode* reverseBetween(struct ListNode* head, int m, int n){
if(m == 1){
return reverseN(head,n);
}
head->next = reverseBetween(head->next, m-1, n-1);
return head;
}
本文借鉴了labuladong 的题解。也推荐更多的朋友去学习借鉴labuladong 的文章。可关注他的公众号labuladong