原题链接
难度: m i d d l e \color{orange}{middle} middle
题目描述
给你单链表的头指针 h e a d head head 和两个整数 l e f t left left 和 r i g h t right right ,其中 l e f t < = r i g h t left <= right left<=right 。请你反转从位置 l e f t left left 到位置 r i g h t right right 的链表节点,返回 反转后的链表 。
示例 1:
输入:head = [1,2,3,4,5], left = 2, right = 4
输出:[1,4,3,2,5]
示例 2:
输入:head = [5], left = 1, right = 1
输出:[5]
提示:
- 链表中节点数目为 n n n
- 1 < = n < = 500 1 <= n <= 500 1<=n<=500
- − 500 < = N o d e . v a l < = 500 -500 <= Node.val <= 500 −500<=Node.val<=500
- 1 < = l e f t < = r i g h t < = n 1 <= left <= right <= n 1<=left<=right<=n
进阶: 你可以使用一趟扫描完成反转吗?
算法
(模拟) O ( n ) O(n) O(n)
假设初始链表如下所示:
第一步,我们先将 m 到 n 之间的指针翻转(不包含第 m个节点),如下所示:
第二步我们将 m 的指针指向 c ,将 a 的指针指向 n ,如下所示:
此时我们就完成了 m 到 n 之间的翻转!
C++ 代码
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverseBetween(ListNode* head, int left, int right) {
auto dummy = new ListNode(0, head);
auto a = dummy;
for (int i = 0; i < left - 1; i ++) a = a->next;
auto b = a->next, c = b->next;
for (int i = 0; i < right - left; i ++) {
auto d = c->next;
c->next = b;
b = c, c = d;
}
a->next->next = c;
a->next = b;
return dummy->next;
}
};