LeetCode题解之92. Reverse Linked List II

问题链接

问题描述

Given the head of a singly linked list and two integers left and right where left <= right, reverse the nodes of the list from position left to position right, and return the reversed list.

Example 1:

Input: head = [1,2,3,4,5], left = 2, right = 4
Output: [1,4,3,2,5]

Example 2:

Input: head = [5], left = 1, right = 1
Output: [5]

Constraints:

  • The number of nodes in the list is n.

  • 1 <= n <= 500

  • -500 <= Node.val <= 500

  • 1 <= left <= right <= n

    Follow up: Could you do it in one pass?

解题思路

对于链表反转相信大家都不陌生,这道题是链表反转的升级版,不是反转整个链表,而是反转指定的两个结点之间的链表(包含指定的这两个结点),不管是反转整个链表还是反转链表的某一部分,都离不开「反转」这个基本操作,我们先来复习一下,链表反转的核心代码如下:

public ListNode reverse(ListNode head) {
    if ( Objects.isNull(head)) {
        return head;
    }
    ListNode p = head, q = head.next, t;
    head.next = null;
    while(q != null){
        t = q.next;
        q.next = p;
        p = q;
        q = t;
    }
    return p;
}

对于这道题目而言,由于不是反转整个链表,所以我们要关注三个部分:1. 被反转的链表之前的部分;2. 被反转的链表;3. 被反转的链表之后的部分。我们需要在链表反转后将这三个部分重新连接起来。举个例子,假设有下面这样一个链表,left 为 3,right 为 6。注意:left 和 right 指的是序号,left 为 3 就是指从左往右数第 3 个结点(从 1 开始计数)。

橙色的部分是我们要反转的部分,反转之后为9->8->4->2,然后要把5->79->8->4->26->3->1首尾相连,组成新的链表。所以我们要记录下反转后的部分的头结点(第 6 个结点)和尾结点(第 2 个结点),以及第 2 个结点和第 7 个结点,这样才能把这三个部分连接起来。

还有一种特殊情况是,当 left 为 1 的时候,整个链表只有被反转的部分以及被反转的链表之后的部分。为了统一处理,我们定义一个 headPre 结点,保证被反转的链表之前总是有结点的。无论 left 等于几,最后只要返回 headPre.next 就好了。

完整代码如下:

public ListNode reverseBetween(ListNode head, int left, int right) {
    if (left == right) {
        return head;
    }
    ListNode p = head, headPre = new ListNode(-1);
    headPre.next = head;
    ListNode leftPre = headPre;
    int i = 1;
    while (i < left && Objects.nonNull(p)) {
        p = p.next;
        leftPre = leftPre.next;
        i++;
    }
    if (Objects.isNull(p) || Objects.isNull(p.next)) {
        return head;
    }
    ListNode leftNode = p;
    ListNode q = p.next;
    ListNode t;
    while (true) {
        t = q.next;
        q.next = p;
        p = q;
        i++;
        if (Objects.isNull(t) || i == right) {
            break;
        }
        q = t;
    }
    leftPre.next = q;
    leftNode.next = t;
    return headPre.next;
}

相关题目

链表

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值