反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明: 1 ≤ m ≤ n ≤ 链表长度。
示例:
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
解题思路
- prev 指针初始化为 null,cur 指针初始化为链表的 head
- 一步步地向前推进 cur 指针,prev 指针跟随其后
- 直到 cur 指针到达从链表头起的第 m 个结点,这就是我们反转链表的起始位置
- 引入两个额外指针,分别称为 tail 和 con。tail 指针指向从链表头起的第 m 个结点,此结点是反转后链表的尾部,故称为 tail。con 指针指向第 m
个结点的前一个结点,此结点是新链表的头部
- tail 和 con 指针在算法开始时被初始化,在算法最后被调用,用于完成链表反转 如前文所解释的那样,抵达第 m 个结点后,在用到上述两个指针前,先迭代地反转链接。不断迭代,直到完成指向第 n 个结点的链接。此时,prev 指针会指向第 n 个结点。
- 我们使用 con 指针来连接 prev 指针,这是因为 prev 指针当前指向的结点(第 n 个结点)会代替第 m 个结点的位置。 类似地,我们利用 tail 指针来连接 prev 指针之后的结点(第 n+1 个结点)
代码实现
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @param {number} m
* @param {number} n
* @return {ListNode}
*/
var reverseBetween = function(head, m, n) {
let prev = null
let cur = head
while(m-- > 1){
n--
prev = cur
cur = cur.next
}
let con = prev
let tail = cur
while(n-- > 0){
[cur.next,prev,cur] = [prev,cur,cur.next]
}
if(con){
con.next = prev
}else{
head = prev
}
tail.next = cur
return head
};
性能
时间复杂度:
空间复杂度: