[路飞]_算法成长之路五,反转链表Ⅱ

97 阅读2分钟

个人算法成长之路五!!!定期更新一些刷题过程中个人的思路以及理解。有兴趣的朋友们可以互动交流哈~

题目:

leetcode-92. 反转链表 II

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

示例 1:

输入: head = [1,2,3,4,5], left = 2, right = 4
输出: [1,4,3,2,5]

示例 2:

输入: head = [5], left = 1, right = 1
输出: [5]

解题思路:

方法一:迭代

很多人叫他穿针引线法,其实我认为本身就是一种迭代,所以就暂且叫他迭代法吧。 步骤: 1.记录left前面一个节点和right后面一个节点; 2.在left和right处将需要反转的链表截取; 3.截取后反转链表; 4.pre.next指向反转后的链表的head,反转后的链表的结尾的next指向right.next

var reverseBetween = function(head, left, right) {
    const newNode = new ListNode(0,head);
    let pre = newNode;
    
   //left
   //从虚拟头节点走 left - 1 步,来到 left 节点的前一个节点
    for(let i = 0; i < left - 1; i++) {
        pre = pre.next;
    }

    //right
    //从 pre 再走 right - left + 1 步,来到 right 节点
    let rightNode = pre;
    for(let i = 0; i < right-left+1; i++) {
        rightNode = rightNode.next;
    }

    //切断出子链表
    let leftNode = pre.next;
    let curr = rightNode.next;  //right右侧下一个节点

    //切断链接
    rightNode.next = null;
    pre.next = null;

    // 第 4 步:同第 206 题,反转链表的子区间
    reverseList(leftNode);

    pre.next = rightNode;
    leftNode.next = curr;
    return newNode.next


};

var reverseList = function(head) {
    let prev = null;
    let curr = head;
    while(curr) {
        const next = curr.next;
        curr.next = prev;
        prev = curr;
        curr = next;

    }
    return prev
}

这种方法连续遍历两次,如果链表比较长的话,很显然,会有影响。

方法二: 头插法

这个方法的思路就是,在需要反转的区间里,每遍历到一个节点,让这个新节点来到反转部分的起始位置。如图所示

1615105242-ZHlvOn-image.png

  • curr:指向待反转区域的第一个节点 left;
  • next:永远指向 curr 的下一个节点,循环过程中,curr 变化以后 next 会变化;
  • pre:永远指向待反转区域的第一个节点 left 的前一个节点,在循环过程中不变。

具体步骤就是:

  • 先将 curr 的下一个节点记录为 next;
  • 执行操作 ①:把 curr 的下一个节点指向 next 的下一个节点;
  • 执行操作 ②:把 next 的下一个节点指向 pre 的下一个节点;
  • 执行操作 ③:把 pre 的下一个节点指向 next。
var reverseBetween = function(head, left, right) {
    // 设置 dummyNode 是这一类问题的一般做法
    const dummy_node = new ListNode(-1);
    dummy_node.next = head;
    let pre = dummy_node;
    for (let i = 0; i < left - 1; ++i) {
        pre = pre.next;
    }

    let cur = pre.next;
    for (let i = 0; i < right - left; ++i) {
        const next = cur.next;
        cur.next = next.next;
        next.next = pre.next;
        pre.next = next;
    }
    return dummy_node.next;
};