92. Reverse Linked List II(反转链表 II)
1. 题目描述
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明: 1 ≤ m ≤ n ≤ 链表长度。
示例:
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
2. 迭代(Iteration)& 递归(Recursion)
2.1 解题思路
首先这题是206. 反转链表的升级版,而且上一题是本题的一种特殊情况,所以这题的解题思路和代码也可以用于上一题。我们先来看看几个例子:
我们发现两个重要的线索:
1)m->next都指向nNext;
2)如果m == head,返回n为头结点;反之,mPre->next = n,返回head为头结点;
所以说,我们只要找到这四个节点,就能完成整个链表的拼接。那么剩下的问题就只是如何翻转m ~ n范围内的链表了。首先,先找到m的节点,这个简单,直接for循环就能找到,顺带也找到了mPre。然后讲解一下主要的翻转思路,递归和迭代通用哒。初始化pre = nullptr, cur = mNode, next = mNode->next,遵循下面步骤:
- cur 指向 pre,完成翻转;
- pre指向cur,cur指向next,next指向next的下一个节点,m++;
- 重复1. 直到m == n + 1;
这里解释一下为什么是m == n + 1,而不是m == n。先来看看下面的流程图加深理解:
我们看到,B、C、D都要翻转一次,一共需要翻转三次,m - n = 4 - 2 = 2 + 1 = 3,所以m == n + 1;这部分对应代码:2.2.1 迭代(Iteration)
递归的翻转思路是一样哒,并木有太多的区别,大家看看代码理解一下就OK啦~ 有什么不明白的欢迎留言,有问必答哒~ 这部分对应代码:2.2.2 递归(Recursion)
2.2 实例代码
2.2.1 迭代(Iteration)
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
//if (!head) return nullptr; // 1 ≤ m ≤ n ≤ 链表长度
ListNode* mNode = head, * mPreNode = nullptr;
for (int i = 1; i < m && mNode; i++) { mPreNode = mNode; mNode = mNode->next; } // 找到m所指的节点
assert(mNode);
// 反转链表,并且找到n所指的节点
ListNode* pre = nullptr, * cur = mNode, * next = mNode->next;
while (m != n + 1) {
cur->next = pre;
pre = cur;
cur = next;
if (next) next = next->next;
m++;
}
ListNode* nNode = pre, * nNext = cur; // 为了方便理解,用新的变量名
mNode->next = nNext;
if (mNode == head) return nNode;
mPreNode->next = nNode;
return head;
}
};
2.2.2 递归(Recursion)
class Solution {
ListNode* nNext = nullptr;
// 函数重载
ListNode* reverseBetween(ListNode* node, ListNode* pre, int count, int n) {
ListNode* temp = node->next;
node->next = pre;
if (!temp || count == n) { nNext = temp; return node; }
return reverseBetween(temp, node, count + 1, n);
}
public:
ListNode* reverseBetween(ListNode* head, int m, int n) {
//if (!head) return nullptr; // 1 ≤ m ≤ n ≤ 链表长度
ListNode* mNode = head, * mPreNode = nullptr;
for (int i = 1; i < m && mNode; i++) { mPreNode = mNode; mNode = mNode->next; } // 找到m所指的节点
assert(mNode);
ListNode* nNode = reverseBetween(mNode, nullptr, m, n);
mNode->next = nNext;
if (mNode == head) return nNode;
mPreNode->next = nNode;
return head;
}
};