【刷题-牛客】链表内指定区间反转

本文介绍了如何在链表中实现指定区间[m,n]的反转,使用核心思想是遍历链表找到子链表起止节点,然后进行头插法反转并重新连接。时间复杂度为O(N),空间复杂度为O(1)。
摘要由CSDN通过智能技术生成

题目链接

链表内指定区间反转_牛客题霸_牛客网 (nowcoder.com)

题目描述

在这里插入图片描述

核心思想

遍历链表的过程中在进行原地翻转

  • [m,n]翻转区间记作子链表,找到子链表的 起始节点 left 和 终止节点 right
  • 记录在链表中 子链表起始节点的前驱节点 leftPre 和子链表 终止节点的后继结点 rightNext
  • 对子链表进行反转处理后与leftPre 和rightNext重新相连
  • 为了防止头结点 head 的多种情况的讨论,选择 另声明一个虚拟头结点 newHead 作为遍历的起点

详细图解

  • 按图索骥

在这里插入图片描述


  • 开始头插

在这里插入图片描述


  • 头插结束

)


  • 子链表重新链接

在这里插入图片描述


代码实现

import java.util.*;

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * @param head ListNode类
     * @param m    int整型
     * @param n    int整型
     * @return ListNode类
     */

    //我们把[m,n]之间的节点当做是子链表
    public ListNode reverseBetween(ListNode head, int m, int n) {
        //虚拟头结点
        ListNode newHead = new ListNode(-1);
        newHead.next = head;//把虚拟头结点连入链表中

        //找到子链表的起始节点left和终止节点right(要求记录下左子链表左节点的前驱节点)

        ListNode leftPre = newHead;
        while (m > 1) {
            leftPre = leftPre.next;
            m--;
        }
        //while结束之后保留的leftPre即起始节点的前驱结点
        ListNode left = leftPre.next;//子链表的起始节点

        ListNode right = newHead;
        while (n > 0) {
            right = right.next;
            n--;
        }
        ListNode rightNext = right.next;//保留的rightNext即终止节点的后继结点

        //子链表进行头插
        ListNode subHead = left;//子链表的头结点
        ListNode cur = subHead.next;
        while (cur != rightNext) {
            ListNode curNext = cur.next;
            cur.next = subHead;
            subHead = cur;
            cur = curNext;
        }

        //开始链接子链表
        leftPre.next = subHead;
        left.next = rightNext;

        return newHead.next;//返回链表原头结点
    }

    static class ListNode {
        int val;
        ListNode next = null;

        public ListNode(int val) {
            this.val = val;
        }
    }
}

复杂度分析

  1. 时间复杂度

    O(N) ,最坏情况下,需要遍历整个链表

  2. 空间复杂度

    O(1) ,使用到常数个变量

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值