【leetcode】92. 反转链表 II

89 阅读1分钟

leetcode-92.png

翻转链表中的部分,由206题的封装后,处理这一题只需要细心即可
处理好头节点,使用pre进行遍历,保存四处节点,便于后面衔接节点

这里设置dummy节点的原因是防止left=1,此时preLeftNode节点就不存在了

解法一:递归反转

var reverseBetween = function (head, left, right) {
    let dummy = new ListNode(-1)
    dummy.next = head
    let pre = dummy
    let cnt = 0
    // 保存反转节点的起始以及终点位置
    let leftNode = null, rightNode = null
    // 保存反转节点前后的节点
    let leftConnectNode = null, rightConnectNode = null
    while (pre) {
        if (cnt === left - 1) {
            // 保存起始节点的前一节点
            leftConnectNode = pre
            // 保存当前反转的起始节点
            leftNode = leftConnectNode.next
        }
        if (cnt === right) {
            // 保存反转的终点
            rightNode = pre
            // 保存终点的下一节点
            rightConnectNode = rightNode.next
            // 因为要反转,肯定要给终点置空,不然会导致后面的所有都反转
            rightNode.next = null // 部分链表的终点
            break
        }
        // 计数器
        cnt++
        // 挪向下一节点
        pre = pre.next
    }
    // 反转left-right之间的链表
    let list = reverse(leftNode)
    // 衔接左边部分
    leftConnectNode.next = list
    // leftNode变成反转后的终点,衔接右边部分
    leftNode.next = rightConnectNode
    return dummy.next
};

var reverse = function (head) {
    if (!head || !head.next) return head
    let newHead = reverse(head.next)
    head.next.next = head
    head.next = null
    return newHead
}

节点标记.png

解法二:迭代原地反转(推荐)

var reverseBetween = function (head, left, right) {
    let dummy = new ListNode(-1);
    dummy.next = head;
    pre = dummy;
    for (let i = 1; i < left; ++i) {
        pre = pre.next;
    }
    let cur = pre.next;
    for (let i = 0; i < right - left; ++i) {
        let next = cur.next;
        cur.next = next.next;
        next.next = pre.next;
        pre.next = next;
    }
    return dummy.next;
};
dummy -> 1 -> 2 -> 3 -> 4 -> 5
dummy -> 1 -> 3 -> 2 -> 4 -> 5
dummy -> 1 -> 4 -> 3 -> 2 -> 5

节点指向.png