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指针