【力扣】92. 反转链表 II <链表指针>

【力扣】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]
【力扣】92. 反转链表 II <链表指针>_第1张图片
示例 2
输入:head = [5], left = 1, right = 1
输出:[5]

提示
链表中节点数目为 n
1 <= n <= 500
-500 <= Node.val <= 500
1 <= left <= right <= n

题解

一次遍历「穿针引线」反转链表(头插法)。
思想是:在需要反转的区间里,每遍历到一个节点,让这个新节点来到反转部分的起始位置。

输入
在这里插入图片描述
整个流程
【力扣】92. 反转链表 II <链表指针>_第2张图片

实现原理
三个指针变量 precurrnext 来记录反转的过程中需要的变量,它们的意义如下:

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

具体实现

  • 先将 curr 的下一个节点记录为 next
  • 执行操作 ①:把 curr 的下一个节点指向 next 的下一个节点;
  • 执行操作 ②:把 next 的下一个节点指向 pre 的下一个节点;
  • 执行操作 ③:把 pre 的下一个节点指向 next。
	//先将 curr 的下一个节点记录为 next
	next = cur.next;
	// 操作1:把 curr 的下一个节点指向 next 的下一个节点;
	cur.next = next.next;
	// 操作2:把 next 的下一个节点指向 pre 的下一个节点
	next.next = pre.next;
	// 操作3:把 pre 的下一个节点指向 next。
	pre.next = next;

【力扣】92. 反转链表 II <链表指针>_第3张图片
完成以后链表拉直后:
【力扣】92. 反转链表 II <链表指针>_第4张图片
同理继续。同样需要注意 穿针引线 操作的先后顺序:

【力扣】92. 反转链表 II <链表指针>_第5张图片
【力扣】92. 反转链表 II <链表指针>_第6张图片
【力扣】92. 反转链表 II <链表指针>_第7张图片
在这里插入图片描述

class ListNode {
    int val;
    ListNode next;
    ListNode() {}
    ListNode(int val) { this.val = val; }
    ListNode(int val, ListNode next) { this.val = val;this.next = next; }
}

//整体思想:在需要反转的区间里,每遍历到一个节点,让这个新节点来到反转部分的起始位置
public class Solution {
    public ListNode reverseBetween(ListNode head, int left, int right) {

        // 设置 dummyNode 是这一类问题的一般做法
        ListNode dummyNode = new ListNode(-1);
        dummyNode.next = head;

        // pre:永远指向待反转区域的第一个节点 left 的前一个节点,在循环过程中不变。
        ListNode pre = dummyNode;
        for (int i = 0; i < left - 1; i++) {
            pre = pre.next;
        }

        // curr:指向待反转区域的第一个节点 left
        ListNode cur = pre.next;
        // next:永远指向 curr 的下一个节点,循环过程中,curr 变化以后 next 会变化
        ListNode next;

        for (int i = 0; i < right - left; i++) {
            //先将 curr 的下一个节点记录为 next
            next = cur.next;

            // 操作1:把 curr 的下一个节点指向 next 的下一个节点;
            cur.next = next.next;

            // 操作2:把 next 的下一个节点指向 pre 的下一个节点
            next.next = pre.next;

            // 操作3:把 pre 的下一个节点指向 next。
            pre.next = next;
        }
        return dummyNode.next;
    }
}

你可能感兴趣的:(#,力扣及OJ,Java相关,leetcode,链表,算法)