Reverse a linked list from position m to n.
Do it in-place and in one-pass.
For example:
Given
1->2->3->4->5->NULL
,
m = 2 and n = 4,
return 1->4->3->2->5->NULL
.
Note:
Given m, n satisfy
the following condition:
1 ≤ m ≤ n ≤
length of list.
解题分析:这个题目就是很容易断链,需要使用多个暂存结点
首先,只要是单链表反转,我们最先应该想到的是 头插法
单链表的头插法是 逆序
单链表的尾插法是 正序
确定头插法之后,我们需要注意m可以等于1,这意味着,第一个节点也可能逆转,出现了 头节点和其余结点操作不统一的情况
这时,我们应该想到 为了是 头节点和其余结点操作统一起来 有两种办法:1.
二级指针 2. 虚拟一个前置结点指向 链表第一个节点
class Solution {
public:
ListNode *reverseBetween(ListNode *head, int m, int n) {
if (head == nullptr) return nullptr;
assert(m >= 1 && n >= 1 && m <= n);
if (m == n) return head;ListNode* newHead = new ListNode(0);
newHead->next = head;
ListNode* cur = newHead;
for (int i = 0; i < m - 1; ++i) {
cur = cur->next;
}
ListNode* prev = cur;
cur = cur->next;
ListNode* mthNode = cur;
ListNode* mthHead = cur;
ListNode* nextNode = cur->next;
for (int i = 0; i < n - m; ++i) {
cur = nextNode;
nextNode = cur->next;
cur->next = mthHead;
mthHead = cur;
}
prev->next = mthHead;
mthNode->next = nextNode;
return newHead->next;
}
};
我们以 1 --> 2 --> 3 --> 4 --> 5 --> NULL 为例
m = 2, n = 4
也就是我们需要逆转 2 --> 3 --> 4
step1. 虚拟一个前置结点指向链表第一个节点
step2. 前进m-1步到达需要反转区间的前1个结点 即结点1,代码中对应的 prev指针
step3. 再前进1步,达到反转区间的第一个节点,设置两个暂存结点
mthHead 和 mthNode
mthHead始终指向区间 2 -->3 --> 4的头节点
step4. 然后前进n-m步,每前进一步都需要事先 把 cur->next 保存起来,防止断链
step5. 循环结束后, 链表表现为3段: 1(第1段) 4 --> 3 --> 2(第2段)
5-->NULL(第3段)
所以我们需要两次链接的操作,第1段和第2段链接使用预先暂存的prev指针,第2段和第3段链接使用预先暂存的 mthNode指针
step6. 返回链表的第一个节点指针,即虚拟结点的next指针
Leetcode:Reverse Linked List II 反转链表区间,布布扣,bubuko.com