思考
题目要求:给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回反转后的链表。
示例: 给出的是 1->2->3->4->5, left = 2, right = 4
1 -> 2 -> 3 -> 4 -> 5
left right
1 -> 4 -> 3 -> 2 -> 5
- 从示例中我们可以看出链表需要反转的节点是 2、3、4 ,
- 我们可以将他们看成一个链表中的小链表 2->3->4 做反转链表操作 4->3->2
- 然后原链表首尾拼接组成最终结果链表 1 4->3->2 5 => 1->4->3->2->5
解题思路
- 首先我们确定待反转小链表的头节点(由于小链表起始点可能为链表的第一个节点,所以我们需要虚拟头节点 hair 作为链表的第一个节点)
- 开始做反转操作,由于反转链表是到 right 位置停止, 所以链表反转操作需要做 right - left + 1 次(+1 是因为第一次要将头节点指向NUll)
- 最后将链表头节点、反转后的小链表、链表尾节点拼接。
设:
hair -> 1 -> 2 -> 3 -> 4 -> 5
left right
hair -> 1 -> 2 -> 3 -> 4 -> 5
hair 1 -> 2 -> 3 -> 4 -> 5
hair 4 -> 3 -> 2 -> 1 5
hair -> 4 -> 3 -> 2 -> 1 -> 5
代码
var reverse = function (head, cnt) {
let pre = null, cur = head;
while (cnt--) {
let next = cur.next;
cur.next = pre;
pre = cur;
cur = next;
}
head.next = cur;
return pre;
}
var reverseBetween = function(head, left, right) {
// 如果链表为空,或者操作 left 和 right 位置相等,就返回原链表
if (!head && left == right) return head;
// 设置头节点来保存
let hair = new ListNode(-1, head), pre = hair, cnt = right - left + 1;
while (--left) {
pre = pre.next;
}
pre.next = reverse(pre.next, cnt);
return pre;
};