LeetCode——92. 反转链表 II

195 阅读2分钟

反转从位置 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
};

性能

时间复杂度:O(n)

空间复杂度:O(1)