首页 > 其他分享 >【链表】Leetcode 92. 反转链表 II【中等】

【链表】Leetcode 92. 反转链表 II【中等】

时间:2024-05-27 14:04:56浏览次数:12  
标签:pre II head ListNode next 链表 92 节点

反转链表 II

  • 给你单链表的头指针 head 和两个整数 left 和 right ,其中 left <= right 请你反转从位置 left 到位置 right 的链表节点,返回 反转后的链表 。

示例 1:
在这里插入图片描述
输入:head = [1,2,3,4,5], left = 2, right = 4
输出:[1,4,3,2,5]

解题思路1

1、遍历链表:

  • 找到 left 前面的节点(preLeft),以及 left 节点本身(leftNode)。
  • 找到 right 节点(rightNode),以及 right 后面的节点(postRight)。
    2、反转部分链表:
  • 将 leftNode 到 rightNode 之间的节点进行反转。
    3、重新连接:
  • 将 preLeft 的 next 指向 rightNode。
  • 将 leftNode 的 next 指向 postRight。

java实现1

public class ReverseBetween {

    public static class ListNode {
        int val;
        ListNode next;

        ListNode(int x) {
            val = x;
        }
    }

    public ListNode reverseBetween(ListNode head, int left, int right) {
        // 创建虚拟头节点,简化边界处理
        ListNode dummyNode = new ListNode(-1);
        dummyNode.next = head;

        ListNode preLeft = dummyNode;
        // 第 1 步:找到 left 节点的前一个节点 pre
        for (int i = 0; i < left - 1; i++) {
            preLeft = preLeft.next;
        }

        // 第 2 步:找到 right 节点
        ListNode rightNode = preLeft;
        for (int i = 0; i < right - left + 1; i++) {
            rightNode = rightNode.next;
        }

        // 第 3 步:切断出一个子链表(截取链表)
        ListNode leftNode = preLeft.next;
        ListNode postRight = rightNode.next;

        // 切断链接
        preLeft.next = null;
        rightNode.next = null;

        // 第 4 步:反转链表的子区间
        reverseLinkedList(leftNode);

        // 第 5 步:接回到原来的链表中
        preLeft.next = rightNode;
        leftNode.next = postRight;

        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;
        }
    }


    public static void main(String[] args) {
        ReverseBetween reverseBetween = new ReverseBetween();

        // 创建示例链表 1->2->3->4->5
        ListNode head = new ListNode(1);
        head.next = new ListNode(2);
        head.next.next = new ListNode(3);
        head.next.next.next = new ListNode(4);
        head.next.next.next.next = new ListNode(5);

        // 测试反转第2到第4个节点
        ListNode newHead = reverseBetween.reverseBetween(head, 2, 4);
        printList(newHead); // 输出: 1->4->3->2->5
    }

    // 辅助方法:打印链表
    public static void printList(ListNode head) {
        ListNode current = head;
        while (current != null) {
            System.out.print(current.val);
            if (current.next != null) {
                System.out.print("->");
            }
            current = current.next;
        }
        System.out.println();
    }
}

时间空间复杂度1

  • 时间复杂度:O(N),其中 N是链表总节点数。最坏情况下,需要遍历整个链表。

  • 空间复杂度:O(1)。只使用到常数个变量。

解题思路2

解题思路1缺点是:如果 left 和 right 的区域很大,恰好是链表的头节点和尾节点时,找到 left 和 right 需要遍历一次,反转它们之间的链表还需要遍历一次,虽然总的时间复杂度为 O(N),但遍历了链表 2 次。

1、初始化和定位:

  • 使用指针 pre 遍历到 left 前一个节点,定位到反转区间的前一个节点。
    局部反转:

2、使用三个指针 pre、cur 和 next 进行反转操作:

  • pre 指向反转区间的前一个节点。

  • cur 指向当前需要反转的节点。

  • next 指向当前节点的下一个节点,用于在反转过程中进行位置交换。
    3、反转区间:

  • 通过逐个移动 cur 和 next 节点的位置,在反转区间内执行交换操作,完成局部反转。

图解:
在这里插入图片描述

在这里插入图片描述
核心代码分析:

   			// 先将 curr 的下一个节点记录为 next;
            next = cur.next;
            //执行操作1:把 curr 的下一个节点指向 next 的下一个节点
            cur.next = next.next;
            //执行操作2:把 next 的下一个节点指向 pre 的下一个节点
            next.next = pre.next;
            //执行操作3:把 pre 的下一个节点指向 next
            pre.next = next;

在这里插入图片描述
在这里插入图片描述
后续同理
在这里插入图片描述
在这里插入图片描述

java实现2

public class ReverseBetween {

    public static class ListNode {
        int val;
        ListNode next;

        ListNode(int x) {
            val = x;
        }
    }

    public ListNode reverseBetween(ListNode head, int left, int right) {
        // 设置 dummyNode 是这一类问题的一般做法
        ListNode dummyNode = new ListNode(-1);
        dummyNode.next = head;
        ListNode pre = dummyNode;
        //找到pre结点
        for (int i = 0; i < left - 1; i++) {
            pre = pre.next;
        }
        //当前current节点
        ListNode cur = pre.next;
        ListNode next;
        
        for (int i = 0; i < right - left; i++) {
            // cur的下一个节点赋值给next
            next = cur.next;
            //cur指向next指向的节点
            cur.next = next.next;
            //next指向pre指向的节点
            next.next = pre.next;
            //pre指向next
            pre.next = next;
        }
        return dummyNode.next;
    }


    public static void main(String[] args) {
        ReverseBetween reverseBetween = new ReverseBetween();

        // 创建示例链表 1->2->3->4->5
        ListNode head = new ListNode(1);
        head.next = new ListNode(2);
        head.next.next = new ListNode(3);
        head.next.next.next = new ListNode(4);
        head.next.next.next.next = new ListNode(5);

        // 测试反转第2到第4个节点
        ListNode newHead = reverseBetween.reverseBetween(head, 2, 4);
        printList(newHead); // 输出: 1->4->3->2->5
    }

    // 辅助方法:打印链表
    public static void printList(ListNode head) {
        ListNode current = head;
        while (current != null) {
            System.out.print(current.val);
            if (current.next != null) {
                System.out.print("->");
            }
            current = current.next;
        }
        System.out.println();
    }
}

时间空间复杂度2

  • 时间复杂度:O(N),其中 N 是链表总节点数。最多只遍历了链表一次,就完成了反转。

  • 空间复杂度:O(1)。只使用到常数个变量。

标签:pre,II,head,ListNode,next,链表,92,节点
From: https://blog.csdn.net/FLGBgo/article/details/139231375

相关文章

  • Codeforces Round 927 (Div. 3) D. Card Game 题解 贪心
    CardGame题目描述Twoplayersareplayinganonlinecardgame.Thegameisplayedusinga32-carddeck.Eachcardhasasuitandarank.Therearefoursuits:clubs,diamonds,hearts,andspades.Wewillencodethemwithcharacters‘C’,‘D’,‘H’,......
  • 链表4(法二)------7-4 sdut-C语言实验-单链表中重复元素的删除
    7-4sdut-C语言实验-单链表中重复元素的删除分数20全屏浏览切换布局作者 马新娟单位 山东理工大学按照数据输入的相反顺序(逆位序)建立一个单链表,并将单链表中重复的元素删除(值相同的元素只保留最后输入的一个)。输入格式:第一行输入元素个数n(1<=n<=15);第二......
  • 链表6(法二好理解)------ 7-6 sdut-C语言实验-有序链表的归并分数 20
    7-6sdut-C语言实验-有序链表的归并分数20全屏浏览切换布局作者 马新娟单位 山东理工大学分别输入两个有序的整数序列(分别包含M和N个数据),建立两个有序的单链表,将这两个有序单链表合并成为一个大的有序单链表,并依次输出合并后的单链表数据。输入格式:第一行输入M与......
  • 『vulnhub系列』BEELZEBUB- 1 96692f0bce834b9f85ce4fb6710ae52d
    『vulnhub系列』BEELZEBUB-1下载地址:https://www.vulnhub.com/entry/beelzebub-1,742/信息搜集:使用nmap扫描存活主机,发现主机开启了22和80端口nmap192.168.0.*访问80端口的web服务,发现是apache的默认页面使用dirsearch扫描目录dirsearch-u"http://192.168.0.140/"......
  • 单链表
    单链表是内存地址不连续排列的线性表。单链表每个结点都有两个地址,第一个位置存储数据,第二个位置存储下个结点的内存地址。classNode(object):"""单链表结点"""def__init__(self,val):#_item存储数据self.val=val#_next是下一个......
  • Ascii(256个) 编码表 完整码表 ASCII编码 ASCII表 ASCII码 二进制 十进制 八进制 十六进
    目录简介ASCII码表ASCII解释1.控制字符释义(0~31)2.ASCII扩展字符(128~255)ASCII的各种进制简介ascii(AmericanStandardCodeforInformationInterchange )美国信息交换标准代码。是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。等同于国际标准......
  • KubeSphere系列---【离线安装kubeSphere时报错:failed: [k8s_node02] failed to conne
    1.报错信息[root@k8s_masterkubesphere-3.4.1-1.23.15-offline-package]#./kkinitregistry-fconfig-sample.yaml-akubesphere.tar.gz_______||//||||//||//__||_____||//_____......
  • WindowsCA证书服务(二)IIS发放证书
    简介IIS,虽说没怎么用,asp也少了,即使有也DOCKER部署。但是和CA中心配合,最合适的就IIS了吧。安装安装windowsserver2022略加入域略安装IIS添加IIS 角色服务先默认 测试IIShttp 检查根证书运行certmgr,可以看到加入域的计算机是自动获取自己的根证书的。手动申......
  • leetcode力扣 1004. 最大连续1的个数 III
    给定一个二进制数组nums和一个整数k,如果可以翻转最多k个0,则返回数组中连续1的最大个数。示例1:输入:nums=[1,1,1,0,0,0,1,1,1,1,0],k=2输出:6解释:[1,1,1,0,0,1,1,1,1,1,1],翻转两个0后,最长的子数组长度为6。示例2:输入:nums=[0,0,1,1,0,0,1,1,1,0,1,1,0,0,0,1,1......
  • Xperia 1iii 日版 免root 卸载系统程序
    一、开启开发者选项自行百度不再赘述二、安装adb并且配置到环境变量中自行百度不再赘述三、执行批处理文件新建一个bat文件把下面的内容复制进去然后双击执行。每一行代码会删除一个程序@echooffadbshellpmuninstall-k--user0jp.co.nttdocomo.lcsappadbshell......