92. 反转链表 II

·  阅读 212

题目介绍

力扣92题:leetcode-cn.com/problems/re…

image.png

方法一

该题是[反转链表]的变形,思路都是差不多的,我们首先需要定位到left对应节点的上一个节点preLeft,以及right对应的节点的下一个节点nextRight,为什么要定位到这两个节点呢?为了后面反转之后的节点拼接。总体步骤如下:

  • 首先找到preLeftnextRight
  • 将需要反转的部分进行反转
  • 反转之后进行节点拼接

image.png

image.png

代码如下:

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseBetween(ListNode head, int left, int right) {
        if(head == null || head.next == null || right == 1 || left == right) {
            return head;
        }
        ListNode dumy = new ListNode(-1);//哑节点
        dumy.next = head;
        ListNode p = dumy;
        ListNode preLeft = null;//反转部分的左边前一个指针
        ListNode leftNode = null;//left对应的节点
        ListNode rightNode = null;//right对应的节点
        ListNode prev = null;
        ListNode nextRight = null;//反转部分的右边下一个指针
        for(int i = 0 ; p != null ; i++) {
            if(i == left - 1) {
                preLeft = p;
                leftNode = p.next;
            }

            if((i == right) && (p.next != null)) {
                nextRight = p.next;
            }

            if (i == right) {
                rightNode = p;
            }
            p = p.next;
        }
        //开始反转从left到right的节点
        p = leftNode;
        while(p != nextRight) {
            //事先保存cur的下一个节点
            ListNode next = p.next;
            p.next = prev;
            prev = p;
            p = next;
        }
        //将反转之后的节点进行拼接
        preLeft.next = rightNode;
        leftNode.next = nextRight;
        return dumy.next;
    }
}

复杂度分析

  • 时间复杂度:O(n)。
  • 空间复杂度:O(1)。

方法二:双指针-头插法

1、我们定义两个指针,分别称之为 g(guard 守卫) 和 p(point)。

我们首先根据方法的参数 m 确定 g 和 p 的位置。将 g 移动到第一个要反转的节点的前面,将 p 移动到第一个要反转的节点的位置上。我们以 m=2,n=4为例。

2、将 p 后面的元素删除,然后添加到 g 的后面。也即头插法。

3、根据 m 和 n 重复步骤(2)

4、返回 dummyHead.next

image.png

image.png

代码如下:

class Solution {
    public ListNode reverseBetween(ListNode head, int m, int n) {
        // 定义一个dummyHead, 方便处理
        ListNode dummyHead = new ListNode(0);
        dummyHead.next = head;

        // 初始化指针
        ListNode g = dummyHead;
        ListNode p = dummyHead.next;

        // 将指针移到相应的位置
        for(int step = 0; step < m - 1; step++) {
            g = g.next; p = p.next;
        }

        // 头插法插入节点
        for (int i = 0; i < n - m; i++) {
            ListNode removed = p.next;
            p.next = p.next.next;

            removed.next = g.next;
            g.next = removed;
        }

        return dummyHead.next;
    }
}
分类:
后端
标签:
分类:
后端
标签:
收藏成功!
已添加到「」, 点击更改