反转链表 II

308 阅读1分钟

Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情

一、题目

给你单链表的头指针 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]

提示:

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

二、题解

1.解读

简而言之就是需要翻转链表的节点,范围为原head链表中第left个节点到right个节点的所有节点,也保证了left <= right

方法一

具体做法是需要写找到left个节点到right节点的范围,然后就想办法翻转这部分的节点即可。一般对于需要判断边界类的问题就直接往链表头节点前添加一个哑节点,然后就定义一个pre指针指向为待翻转的一个节点,初始的指向哑节点,然后就往后查找到第left个节点,然后pre指针指向这里,现在就可以开始采用头插法来翻转链表节点直到到达第right个节点处停止。头插法顾名思义是将节点从头部一个一个插入,而翻转链表节点的本质上就是后面的节点移动到前面,前面的节点移动到后面。那么翻转就可以直接将第二个节点放到第一个节点前,第三个节点放到第二个节点前,反过来就是将第一个节点放到第二个节点后,第二个节点放到第三个节点后面。具体的将head的需要移动的节点放到翻转后的链表头部,这样移动移动right - left个节点即可。

三、代码 方法一 Java代码

class Solution {
    public ListNode reverseBetween(ListNode head, int left, int right) {
        if (left == right) {
            return head;
        }
        ListNode dumb = new ListNode(0, head);
        ListNode pre = dumb;
        int index = 0;
        while (index++ < left - 1) {
            pre = pre.next;
        }
        head = pre.next;
        while (index++ < right ) {
            ListNode temp = head.next;
            head.next = temp.next;
            temp.next = pre.next;
            pre.next = temp;
        }
        return dumb.next;
    }
}

时间复杂度:O(n),需要一次遍历链表。

空间复杂度:O(1),需要常数个空间变量。