算法通关村第二关——指定区间链表反转问题解析

135 阅读2分钟

1.指定区间反转链表

对应 leetcode 92. 反转链表 II

解题方法:穿针引线法

这道题目的难点在于如何切分出反转区间的链表,然后使这部分链表反转,以及切分后如何让反转区间前的链表,以及反转链表和反转区间后面的链表相连;如果解决上述问题,那么拿下该题轻而易举;

 public static ListNode reverseListNode(ListNode head, int left, int right) {
        if (head == null || head.next == null || left == right) {
            return head;
        }
        // 创建虚拟节点,因为head可能会被改变,因此使用虚拟节点避免复杂的讨论情况
        ListNode dummyNode = new ListNode(-1);
        dummyNode.next = head;
        ListNode temp = dummyNode;
        // 找到 left所在节点的前一个位置,即找到反转链表开始位置的前一个位置
        int num = 0;
        while (num != left - 1) {
            temp = temp.next;
            num++;
        }
        // 反转链表的开始位置
        ListNode leftNode = temp.next;
        //  rightNode 记录的是反转后的链表头节点
        ListNode rightNode = null;
        ListNode next = null;
        // 开始反转链表,终止位置是当 num == right 时,就结束
        // 为什么不是 num==right-1时,结束链表的反转呢?
        // 原因是我们并没有接着 temp来遍历链表,而是来到 temp.next的位置遍历链表,也就是在leftNode位置继续遍历链表;
        // 原来应该是 num+1==right; 现在变成了 num==right; 中间跳过了一个位置
        while (num != right) {
            next = leftNode.next;
            leftNode.next = rightNode;
            rightNode = leftNode;
            leftNode = next;
            num++;
        }
        // 使用中间节点来遍历 rightNode 链表,防止rightNode改变;
        ListNode curRight = rightNode;
        // 遍历到链表结尾
        while (curRight.next != null) {
            curRight = curRight.next;
        }
        // 让rightNode尾节点指向 leftNode 所在的位置 也就是反转区间后面的链表头节点位置,让反转区间和区间后面的位置相连
        curRight.next = leftNode;
        // temp记录的是反转区间前面的链表尾节点的位置,让区间前的位置和反转区间相连,得到完整链表
        temp.next = rightNode;
        // 返回虚拟节点的下一个,也就是新链表的头节点
        return dummyNode.next;
    }

注意:一定要找准反转链表区间的开始和结束的位置,这是至关重要的!!!;

这仅仅只是我的个人理解,虽然提交代码通过了,但也尝试了很久,然后一点点的改进,耗费了我一段时间;

image.png