C/C++ BM2链表内指定区间反转

news2025/3/17 14:03:49

文章目录

  • 前言
  • 题目
  • 1. 解决方案一
    • 1.1 思路阐述
    • 1.2 源码
  • 2. 解决方案二
    • 2.1 思路阐述
    • 2.2 源码
  • 总结

前言

这题是BM1的升级版,不过是把完整的链表翻转变成了指定区间。

题目

在这里插入图片描述

描述
将一个节点数为 size 链表 m 位置到 n 位置之间的区间反转,要求时间复杂度 O(n),空间复杂度 O(1)。
例如:
给出的链表为 1→2→3→4→5→NULL
返回 1→4→3→2→5→NULL

数据范围: 链表长度 0<size≤10000<size≤1000,0<m≤n≤size0<m≤n≤size,链表中每个节点的值满足 ∣val∣≤1000
要求:时间复杂度 O(n) ,空间复杂度 O(n)
进阶:时间复杂度 O(n),空间复杂度 O(1)

示例1
输入:

{1,2,3,4,5},2,4

返回值:

{1,4,3,2,5}

示例2
输入:

{5},1,1

返回值:

{5}


1. 解决方案一

1.1 思路阐述

做完BM1,再做BM2,第一反应就是套用BM1的代码。
这里套用BM1的思路2。
BM1是全局翻转,所以只要从第一个节点开始反转即可;

BM2是区间翻转,因此要找到区间的起始节点,即第m个节点开始的子链表,再把区间m到n的节点翻转,再拼凑前后端链表即可。

代码具体思路如下

  1. 添加表头,定义前序节点;
  2. 找到第m个节点的前一个节点。这里找前一个节点而不是直接定位到第m个节点,因为后续取子链表的时候,如果是m节点,会出现节点个数少1的情况。比如输入{5,3},1,2。在分离前链表的时候,由于pre指向的是m的位置,也就是5,如果把5的后面节点置为空节点,那么相当于倒置的是m后面的节点m1到n的子链表。但是对于我们自定义的这个输入,pre其实应该指向的是头结点-1的位置,头结点后的5,3才是我们要倒置的链表。
  3. 找到第n个节点的位置;
  4. 取两个链表,一个是m开始的链表,一个是n后面的尾链表
  5. 分离子链表,把m前面的链表和m开始的链表断开;把n开始的链表和n后面的尾链表断开;
  6. 翻转m开始的链表(这时候m开始的链表已经是m到n区间的链表了)
  7. 把刚才分离的链表拼接上翻转后的链表
  8. 返回头结点res的下一个节点开始的链表

下面是我画的一个流程草图

在这里插入图片描述

1.2 源码

class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
         //加个表头
        ListNode* res = new ListNode(-1);
        res->next = head;
        //前序节点
        ListNode* pre = res; 
 
        //找到m的前一个节点
        for(int i = 1; i < m; i++){ 
            pre=pre->next;
        }
        //找到n
        ListNode *nNode=pre;
        for(int i = 0; i < n-m+1; i++){ 
            nNode=nNode->next;
        }
        //取子链表
        ListNode *LeftNode=pre->next;
        ListNode *cur=nNode->next;
        
        //分离子链表
        pre->next=nullptr;
        nNode->next=nullptr;

        //翻转区间链表
        reverseLinkList(LeftNode);

        //拼接链表
        pre->next=nNode;
        LeftNode->next=cur;
        //返回去掉表头
        return res->next; 
    }
    void reverseLinkList(ListNode *head)
    {
        ListNode *pre = nullptr;
        ListNode *cur = head;
        while(cur!=nullptr){
            ListNode *next = cur->next;
            cur->next = pre;
            pre = cur;
            cur = next;
        }
    }
};

2. 解决方案二

2.1 思路阐述

相比于第一种方法,这种方法就不涉及到拆分和拼接链表的过程。
方法二是断开要倒置的链表节点,将其插入到前一个节点去,其他保持不变。最主要的是要理清楚节点之间的关系。

  • 添加表头,定义前序节点和当前节点
  • 找到m节点的位置,作为当前节点。前序节点为cur当前节点的前一个节点。
  • 因为n是始终大于m的,所以我们可以使用for循环,翻转m到n之间的节点。

翻转过程如下

  • 首先保存下一个要反转子链表表头temp
  • 将当前节点cur和temp之间断开,将cur直接与反转子链表表头temp的后续节点相连,这一步就是断开cur与temp的关系,同时把temp节点独立出来。
  • 接下来就是一个插入节点的过程;首先就是保证原有链表顺序不发生变化,将temp的下一个节点指向当前节点cur,再将cur的前序节点的下一个节点指向temp,断开cur前序节点和cur之间的关系,并将pre作为temp的前序节点,从而完成倒置效果。
  • 重复上述操作,重复次数即为m到n之间的节点个数。
  • 最后是返回表头节点对应的下一个节点开始的链表。
    下面是我画的草图
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

2.2 源码

class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int m, int n) {
         //加个表头
        ListNode* res = new ListNode(-1);
        res->next = head;
        //前序节点
        ListNode* pre = res; 
        //当前节点
        ListNode* cur = head; 
        //找到m
        for(int i = 1; i < m; i++){ 
            pre = cur;
            cur = cur->next;
        }
        //从m反转到n
        for(int i = m; i < n; i++){ 
            ListNode* temp = cur->next;
            cur->next = temp->next;
            temp->next = pre->next;
            pre->next = temp;
        }
        //返回去掉表头
        return res->next; 
    }
};

总结

这道题是结合了BM1的链表翻转,并增添了遍历指定位置节点、链表断表、插入、组合等操作。难度比上一题BM1加大,核心思想不变,依旧是倒置链表。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1336351.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第二证券:我国股市涨跌幅限制是多少?

我国股市涨跌幅束缚是多少&#xff1f; 1、主板&#xff1a;新股上市后的前5个交易日不设价格涨跌幅束缚&#xff0c;第6个交易日起&#xff0c;涨跌幅束缚为10%。 2、创业板&#xff1a;新股上市后的前5个交易日没有价格涨跌幅束缚&#xff0c;第6个交易日起&#xff0c;涨跌…

基于VUE3+Layui从头搭建通用后台管理系统(前端篇)十七:演示功能模块相关功能实现

一、本章内容 本章实现常见业务功能,包括文章管理、商品管理、订单管理、会员管理等功能。 1. 详细课程地址: https://edu.csdn.net/course/detail/38183 2. 源码下载地址: 点击下载 二、界面预览 三、开发视频 3.1 B站视频地址:

【Jmeter、postman、python 三大主流技术如何操作数据库?】

前言 1、前言 只要是做测试工作的&#xff0c;必然会接触到数据库&#xff0c;数据库在工作中的主要应用场景包括但不限于以下&#xff1a; 功能测试中&#xff0c;涉及数据展示功能&#xff0c;需查库校验数据正确及完整性&#xff1b;例如商品搜索功能 自动化测试或性能测试…

Pytorch深度强化学习2-1:基于价值的强化学习——DQN算法

目录 0 专栏介绍1 基于价值的强化学习2 深度Q网络与Q-learning3 DQN原理分析4 DQN训练实例 0 专栏介绍 本专栏重点介绍强化学习技术的数学原理&#xff0c;并且采用Pytorch框架对常见的强化学习算法、案例进行实现&#xff0c;帮助读者理解并快速上手开发。同时&#xff0c;辅…

swing快速入门(二十九)播放器工具条

注释很详细&#xff0c;直接上代码 上一篇 新增内容 1.工具条按钮添加响应及图标 2.为控件添加滚动条&#xff08;通用&#xff09; 3.在工具按钮之间添加自动间隔 4.设置工具条的可否移动状态&#xff08;默认可移动&#xff09; package swing21_30;import javax.swing…

Spring系列学习二、Spring框架的环境配置

Spring框架的环境配置 一、Java环境配置二、 Spring框架的安装与配置三、Maven与Gradle环境的配置四、IDE环境配置&#xff08;Eclipse与IntelliJ IDEA&#xff09;五、结语 一、Java环境配置 所有编程旅程总是得从基础开始&#xff0c;如同乐高积木大作的基座&#xff0c;首先…

Ubuntu20.04-查看GPU的使用情况及输出详解

1. 查看GPU的使用情况 1.1 nvidia-smi # 直接在终端得到显卡的使用情况 # 不会自动刷新 nvidia-smi# 重定向到文件中 nvidia-smi > nvidia_smi_output.txt# 如果输出的内容部分是以省略号表示的&#xff0c;可以-q nvidia-smi -q 1.2 nvidia-smi -l # 会自动刷新&#x…

Python高级用法:enumerate(枚举)

enumerate&#xff08;枚举&#xff09; 在编写代码时&#xff0c;为了遍历列表并获取每个元素在列表中的索引&#xff0c;我们可以使用Python中的enumerate函数。下面是一个简单的例子&#xff0c;演示了如何使用enumerate函数实现相同的功能。 原始代码片段&#xff1a; i…

keepalived高可用 | 部署Ceph分布式存储

keepalived高可用 | 部署Ceph分布式存储 keepalived高可用1. 配置第二台haproxy代理服务器部署HAProxy 2.为两台代理服务器配置keepalived配置第一台代理服务器proxy (192.168.4.5)配置第二台代理服务器proxy (192.168.4.6)修改DNS服务器 部署ceph分布式存储准备硬件实验环境准…

10个值得收藏的机器视觉标注工具

推荐&#xff1a;用 NSDT编辑器快速搭建可编程3D场景 我们知道寻找良好的图像标记和注释工具对于创建准确且有用的数据集的重要性。 随着图像注释空间的增长&#xff0c;我们看到开源工具的可用性激增&#xff0c;这些工具使任何人都可以免费标记他们的图像并从强大的功能中受益…

Java代理设计模式--静态代理和动态代理

文章目录 代理设计模式概念代理模式的定义与特点代理模式的结构与实现代理模式的应用场景静态代理实例代理模式的扩展动态代理实现方式JDK动态代理与实例Cglib动态代理JDK动态代理与CGLIB对比 代理设计模式 概念 在有些情况下&#xff0c;一个客户不能或者不想直接访问另一个…

【中小型企业网络实战案例 二】配置网络互连互通

​【中小型企业网络实战案例 一】规划、需求和基本配置-CSDN博客 热门IT技术视频教程&#xff1a;https://xmws-it.blog.csdn.net/article/details/134398330?spm1001.2014.3001.5502 配置接入层交换机 1.以接入交换机ACC1为例&#xff0c;创建ACC1的业务VLAN 10和20。 <…

NFC物联网一次性口令认证解决方案

物联网是由无线传感器网络、射频识别(RadioFrequency Identificalion&#xff0c;RFID)网络、互联网等构成的一种复合型网络&#xff0c;具有部分终端设备体积小、存储和计算处理能力弱的特点。顾名思义&#xff0c;物联网就是“物物相连的互联网”&#xff0c;也就是说,物联网…

Visual Studio2022配置ReSharper C++ 常用设置

如需安装免费的可以在下面留言&#xff0c;看到即回复 文章目录 Visual Studio2022配置ReSharper C 常用设置配置Visual Studio2022&#xff0c;使其能够按回车进行补全配置ReSharper C 设置自动弹出配置ReSharper C 的快捷键ReSharper C 去掉注释拼写使用中文注释 如何关闭新版…

OAuth2.0 四种授权方式讲解

一、OAuth2.0 的理解 OAuth2是一个开放的授权标准&#xff0c;允许第三方应用程序以安全可控的方式访问受保护的资源&#xff0c;而无需用户将用户名和密码信息与第三方应用程序共享。OAuth2被广泛应用于现代Web和移动应用程序开发中&#xff0c;可以简化应用程序与资源服务器之…

在国内如何在速卖通上买东西(在速卖通aliexpress上付款)??

一、速卖通aliexpress上购物流程 1. 登录速卖通aliexpress网站&#xff0c;点击“注册”按钮。 2. 输入您的邮箱地址&#xff0c;然后单击“验证/联系”按钮&#xff1b; 3. 使用您的信用卡支付订单金额&#xff0c;点击获取信用卡 4. 在“我的订单管理器”中查看订单信息。 …

学习笔记14——Springboot以及SSMP项目

SpringBoot Springboot项目 IDEA2023只能创建jdk17和21的springboot项目解决 - 嘿嘿- - 博客园 (cnblogs.com)解决IntelliJ IDEA2022.03创建包时&#xff0c;包结构不自动分级显示的问题_idea建包不分级-CSDN博客IDEA调出maven项目窗口_idea maven窗口-CSDN博客 相比于spring的…

【2023下算法课设】Gray码的分治构造算法

Gray码是一个长度为2ⁿ的序列&#xff0c;序列中无相同元素&#xff0c;且每个元素都是长度为n位的二进制位串&#xff0c;相邻元素恰好只有1位不同。例如长度为2的格雷码为&#xff08;000,001,011,010,110,111,101,100&#xff09;&#xff0c;设计分治算法对任意的n值构造相…

如何使用设计模式来解决类与类之间调用过深的问题。

我们将使用责任链模式和装饰者模式的组合。 考虑一个简化的餐厅订单处理系统&#xff0c;其中包括服务员&#xff08;Waiter&#xff09;、厨师&#xff08;Chef&#xff09;和收银员&#xff08;Cashier&#xff09;。订单从服务员开始&#xff0c;然后传递给厨师&#xff0c…

python区块链简单模拟【05】

新增内容&#xff1a;构建去中心化网络 import socket #套接字&#xff0c;利用三元组【ip地址&#xff0c;协议&#xff0c;端口】可以进行网络间通信 import threading #线程 import pickle# 定义一个全局列表保存所有节点 NODE_LIST []class Node(threading.Thread…