力扣92:反转链表II

141 阅读1分钟

题目

给你单链表的头指针 head 和两个整数 leftright ,其中 left <= right 。请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。

解题思路一

穿针引线法:此方法只需遍历循环一次,即可完成。重点在于:找到left的开始节点的前一个节点:即pre节点,pre节点的下一个节点为curr(循环头节点),循环次数为right-left次,每次循环,用穿针引线的方式:第一步,记录curr的next节点;第二步,让curr的next指向next的下一个节点;第三步, 让next节点的next指向pre节点的下一个节点;第四步,让pre节点的next指向next节点即可

var reverseBetween = function(head, left, right) {
    // 这里定义一个虚拟头节点
    let virtual_node = new ListNode(-1);
    virtual_node.next = head;

    // 找到pre节点
    let pre = virtual_node;
    for (let i = 0; i < left - 1; i++) {
        pre = pre.next;
    }

    // 穿针引线
    let curr = pre.next;
    for (let i = 0; i < right - left; i++) {
        let next = curr.next;
        curr.next = next.next;
        next.next = pre.next;
        pre.next = next;
    }

    return virtual_node.next;
};

解题思路二

常规方法:找到pre节点,找到反转节点的最右节点rightNode节点,将中间的链表取出反转,然后将pre的next指向反转后的rightNode节点,将leftNode(反转后的头部节点)的next指向rightNode截取之前的next节点

var reverseBetween = function(head, left, right) {
    // 这里定义一个虚拟头节点
    const virtualNode = new ListNode(-1);
    virtualNode.next = head;

    // 找到pre节点
    let pre = virtualNode;
    for (let i = 0; i < left - 1; i++) {
        pre = pre.next;
    }

    找到反转节点的最右节点
    let rightNode = pre;
    for (let i = 0; i < right - left + 1; i++) {
        rightNode = rightNode.next;
    }

    // 暂存反转前的最左节点和反转链表最右节点的下一个节点
    let leftNode = pre.next;
    let curr = rightNode.next;

    // 切断链表获取需要反转的链表
    pre.next = null;
    rightNode.next = null;

    // 反转链表
    reverseList(leftNode);

    // 接回到原来的链表中
    pre.next = rightNode;
    leftNode.next = curr;
    return virtualNode.next;
};

const reverseList = (head) => {
    let pre = null;
    let cur = head;

    while (cur) {
        const next = cur.next;
        cur.next = pre;
        pre = cur;
        cur = next;
    }
}