题目描述:
给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回反转后的链表 。
示例:
算法思想:
方法一:递归
在上一篇文章 反转链表I 中,我们学会了反转一个完整的链表,在做本题之前,先思考一个容易一点的问题,如何反转一个链表的前N个节点?如图所示:
有没有发现与上一篇文章的区别,就在1这个节点上,上一篇文章是把这个节点指向了null,而这里是把1这个节点指向了4,也就是说,如果我们像上一篇文章一样递归,只需在递归到最后一个节点3的时候,存储一个指向4节点的指针successor,最后把1指向这个指针就可以了。
那么,这个successor怎么去找呢?
我们思考一种更一般的情况,假如反转的节点只有1个怎么办?
if (n == 1) {
// 记录第 n + 1 个节点
successor = head.next;
return head;
}
整体代码如下:
ListNode successor = null; // 后驱节点
// 反转以 head 为起点的 n 个节点,返回新的头结点
ListNode reverseN(ListNode head, int n) {
if (n == 1) {
// 记录第 n + 1 个节点
successor = head.next;
return head;
}
// 以 head.next 为起点,需要反转前 n - 1 个节点
ListNode last = reverseN(head.next, n - 1);
head.next.next = head;
// 让反转之后的 head 节点和后面的节点连起来
head.next = successor;
return last;
}
ok,这个问题已经解决了,我们再来看看今天的这道题目,反转从位置 left 到位置 right 的链表节点,如果left==1,不就是我上面的这种情况了吗,反转前right个节点。
if(left == 1)
reverseN(ListNode head, int right);
如果left != 1呢?如果我们把head的索引视为1,那么我们想从第m个元素开始反转,如果把head.first视为1呢,那么就从m-1个元素开始反转,如果把head.first.first视为1呢…
这就构成了递归
ListNode reverseBetween(ListNode head, int left, int right){
if(left == 1)
return reverseN(ListNode head, int right);
head.first = reverseBetween(head.next, left - 1, right - 1);
return head;
}
复杂度分析:
较难,以后再更。
方法二:穿针引线
同样借助 反转链表I 里面的方法,在此方法上做部分改进。
先分析与上个题目的区别:
不就是前后多个结点嘛,要反转的区间是[left, right],那么我们把left-1和right+1记下来,中间当作一整个一整个链表反转,完事后穿针引线不就可以了嘛
class Solution {
public ListNode reverseBetween(ListNode head, int left, int right) {
// 使用虚拟头节点避免复杂的分类讨论
ListNode dummyNode = new ListNode(-1);
dummyNode.next = head;
ListNode pre = dummyNode;
// 来到 left 节点的前一个节点
for (int i = 0; i < left - 1; i++) {
pre = pre.next;
}
// 来到 right 节点
ListNode rightNode = pre;
for (int i = 0; i < right - left + 1; i++) {
rightNode = rightNode.next;
}
// 切断出一个子链表(截取链表)
ListNode leftNode = pre.next;
ListNode curr = rightNode.next;
// 注意:切断链接
pre.next = null;
rightNode.next = null;
// 反转链表的子区间
reverseLinkedList(leftNode);
// 接回到原来的链表中
pre.next = rightNode;
leftNode.next = curr;
return dummyNode.next;
}
}
复杂度分析:
时间复杂度:O(n)
空间复杂度:O(1)