92_反转链表II

92_反转链表II

 

package 链表;

import 二叉树.二叉搜索树.TreeNode;

/**
 * https://leetcode-cn.com/problems/reverse-linked-list-ii/
 * @author Huangyujun
 *
 *思路: 断链前一个的指针 (pre)
 *片段的最后一个结点: fragLast
 *断链后的第一个指针(post)
 */
public class _92_反转链表II {
     public ListNode reverseBetween(ListNode head, int left, int right) {
            // 因为头节点有可能发生变化,使用虚拟头节点可以避免复杂的分类讨论
            ListNode dummyNode = new ListNode(-1);
            dummyNode.next = head;

            ListNode pre = dummyNode;
            // 第 1 步:从虚拟头节点走 left - 1 步,来到 left 节点的前一个节点
            // 建议写在 for 循环里,语义清晰
            for (int i = 0; i < left - 1; i++) {
                pre = pre.next;
            }

            // 第 2 步:从 pre 再走 right - left + 1 步,来到 post 节点
            ListNode fragLast = pre;
            for (int i = 0; i < right - left + 1; i++) {
                fragLast = fragLast.next;
            }

            // 第 3 步:切断出一个子链表(截取链表)
            ListNode fragFirst = pre.next;
            ListNode post = fragLast.next;

            // 注意:切断链接
            pre.next = null;
            fragLast.next = null;

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

            // 第 5 步:接回到原来的链表中
            pre.next = fragLast;
            
            fragFirst.next = post;
            return dummyNode.next;
        }

        private void reverseLinkedList(ListNode head) {
            // 也可以使用递归反转一个链表
            ListNode pre = null;
            ListNode cur = head;

            while (cur != null) {
                ListNode next = cur.next;
                cur.next = pre;
                pre = cur;
                cur = next;
            }
        }
}

 

posted @ 2021-12-19 23:07  一乐乐  阅读(12)  评论(0)    收藏  举报