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

news2024/11/24 23:04:15

在这里插入图片描述

链表内指定区间反转

  • 题目描述
  • 思路一(暴力破解版)
  • 思路二(技巧反转版)
  • 思路三(递归魔法版)
  • Thanks♪(・ω・)ノ谢谢阅读!!!
  • 下一篇文章见!!!

题目描述

在这里插入图片描述
根据题目描述,大致思路比较顺畅,需要使用链表的插入,创建等内容。

思路一(暴力破解版)

  1. 首先找到第 m-1 个节点并记录
  2. 然后开始反转
  3. 遍历 m - n 链表节点 ,并依次头插到一个新链表中
  4. m-1节点 指向新链表 ,新链表尾指向 n+1 个节点
  5. 完成反转。
typedef struct ListNode node;

struct ListNode* reverseBetween(struct ListNode* head, int m, int n ) {
    //如果 m == n 不需要反转
	if (m == n ) return head;
	// 定义新链表的头尾
    node* new = NULL , *tail = NULL;
    //定义 cur 来指向当前节点 方便遍历
    node* cur = head;
    // 定义m-1节点  n+1节点
    node* mnode = NULL,*nnode = NULL;
    //开始遍历
    int count = 1;
    while(count < m){
        //记录第 m-1 节点
        if(count == m-1){
            mnode = cur;
        }
        cur = cur->next;
        count++;
    }
	//开始反转
    while(count <= n){
    	//记录第 n+1个节点
        if(count == n){
            nnode = cur->next;
        }
        //每次创建新节点 拷贝
        node* newnode = (node*)malloc(sizeof(node));
        newnode->val = cur->val;
		//进行头插  new 为空则直接指向新节点 
        if(new == NULL){
            new = tail = newnode;
        }
        else{
            newnode->next = new;
            new = newnode;
        }
        //迭代
        cur = cur->next;
        count++;
    }
    // 分情况讨论
    // 如果 mnode == NULL 则标明 从头开始反转
    //直接将head = new
    if (mnode == NULL) {
        head = new;
    }
    //反之将 新链表插入在mnode后
    else mnode->next = new;
    // 新链表 指向nnode
    tail->next = nnode;
    return head;
}

运行效果:
在这里插入图片描述

思路二(技巧反转版)

该版本使用了一个十分巧妙的算法,不用额外开辟空间就能完成链表的反转。
在这里插入图片描述
通过从 m 到 n - 1的遍历
逐个将 temp 移到 prev 的后面
完成局部头插。

typedef struct ListNode node;
struct ListNode* reverseBetween(struct ListNode* head, int m, int n ) {
	//定义一个 头结点 ,方便操作
    node* H = (node*)malloc(sizeof(node));
    H->next = head;
	//两个指针 分别指向 当前节点 和 前节点
    node* prev = H,*cur = head;
	// 遍历到 第m-1个节点
    for(int i = 1;i < m; i++){
        prev = cur;
        cur = cur->next;
    }
	//开始反转
    for(int i = m; i<n;i++){
    	// temp 指向 cur后一个节点
        node* temp = cur->next;
        // 将temp移动到 prev 后
        // cur 移动到 temp 位置
        cur->next = temp->next;
        temp->next = prev->next;
        prev->next = temp;
    }
    //返回
    return H->next;
}

运行效果:
在这里插入图片描述

思路三(递归魔法版)

思路来自牛客官方
我们来看看另一种分析:如果m == 1,就相当于反转链表的前 n 元素;如果 m != 1,我们把 head 的索引视为 1,那么我们是想从第 m 个元素开始反转,如果把 head.next 的索引视为1,那相对于 head.next的反转的区间应该是从第 m−1 个元素开始的,以此类推,反转区间的起点往后就是一个子问题,我们可以使用递归处理:

终止条件: 当m == 1,就可以直接反转前n个元素。
返回值: 将已经反转后的子问题头节点返回给上一级。
本级任务: 递归地缩短区间,拼接本级节点与子问题已经反转的部分。

从头开始往后去掉前面不反转的部分

ListNode node = reverseBetween(head.next, m - 1, n - 1)

而每次反转,如果 n == 1,相当于只颠倒第一个节点,如果不是,则进入后续节点(子问题),因此反转过程也可以使用递归:

终止条件: 当n == 1时,只反转当前头节点即可。
返回值: 将子问题反转后的节点头返回。
本级任务: 缩短 n 进入子问题反转,等子问题回到本级再反转当前节点与后续节点的连接。

颠倒后续的节点,直到n=1为最后一个

ListNode node = reverse(head.next, n - 1)

具体做法:

  1. 准备全局变量temp,最初等于null,找到递归到第n个节点时,指向其后一个位置,要将反转部分的起点(即反转后的尾)连接到这个指针。
  2. 按照第一个递归的思路缩短子问题找到反转区间的起点,将反转后的部分拼接到前面正常的后面。
  3. 按照第二个递归的思路缩短终点的子问题,从第n个位置开始反转,反转过程中每个子问题作为反转后的尾,都要指向temp。
 typedef struct ListNode ListNode;
 ListNode* temp = NULL;
 ListNode* reverse(ListNode* head, int n){
        //只颠倒第一个节点,后续不管
        if(n == 1){
            temp = head->next;
            return head;
        }
        //进入子问题
        ListNode* node = reverse(head->next, n - 1);
        //反转
        head->next->next = head;
        //每个子问题反转后的尾拼接第n个位置后的节点
        head->next = temp;
        return node;
}
ListNode* reverseBetween(ListNode* head, int m, int n) {
        //从第一个节点开始
        if(m == 1)
            return reverse(head, n);
        //缩减子问题
        ListNode* node = reverseBetween(head->next, m - 1, n - 1);
        //拼接已翻转
        head->next = node;
        return head;
}

Thanks♪(・ω・)ノ谢谢阅读!!!

下一篇文章见!!!

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

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

相关文章

黑群晖一键修复:root、AME、DTS、转码、CPU型号等

食用方法&#xff1a;SSH连接群晖使用临时root权限执行 AME3.x激活补丁 只适用于x86_64的&#xff1a;DSM7.x Advanced Media Extensions (AME)版本3.0.1-2004、3.1.0-3005 激活过程需要下载官方的解码包&#xff0c;过程较慢&#xff0c;耐心等待。。。 DSM7.1和7.2的AME版…

【开源】SpringBoot框架开发智能教学资源库系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 课程档案模块2.3 课程资源模块2.4 课程作业模块2.5 课程评价模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 课程档案表3.2.2 课程资源表3.2.3 课程作业表3.2.4 课程评价表 四、系统展示五、核心代…

Vulnhub靶机:DC6

一、介绍 运行环境&#xff1a;Virtualbox 攻击机&#xff1a;kali&#xff08;10.0.2.15&#xff09; 靶机&#xff1a;DC6&#xff08;10.0.2.59&#xff09; 目标&#xff1a;获取靶机root权限和flag 靶机下载地址&#xff1a;https://www.vulnhub.com/entry/dc-6,315/…

基于深度置信网络的多模态过程故障评估方法及应用

源自&#xff1a;自动化学报 作者&#xff1a;张凯, 杨朋澄, 彭开香, 陈志文 “人工智能技术与咨询” 发布 摘 要 传统的多模态过程故障等级评估方法对模态之间的共性特征考虑较少, 导致当被评估模态故障信息不充分时, 评估的准确性较低. 针对此问题, 首先, 提出一种共性–…

springboot登录校验

一、登录功能 二、登录校验 2.1 会话技术 2.2 JWT令牌 JWT令牌解析&#xff1a; 如何校验JWT令牌&#xff1f;Filter和Interceptor两种方式。 2.3 过滤器Filter 2.3.1 快速入门 修改上述代码&#xff1a; 2.3.2 详解 2.3.3 登录校验-Filter 2.4 Interceptor拦截器 2.4.1 …

NLP_Transformer架构

文章目录 Transformer架构剖析编码器-解码器架构各种注意力的应用Transformer中的自注意力Transformer中的多头自注意力Transformer中的编码器-解码器注意力Transformer中的注意力掩码和因果注意力 编码器的输入和位置编码编码器的内部结构编码器的输出和编码器-解码器的连接解…

C++重新认知:智能指针

0/# 一、为什么要有智能指针 内存泄露是我们开发大型项目时最为头疼的问题&#xff0c;当我们将对象建立在堆上时&#xff0c;因为需要我们自己手动释放&#xff0c;因此避免不了忘记删除&#xff0c;或者删除时没有考虑清楚情况的问题&#xff0c;从而造成悬挂指针或者是野指针…

UnityShader——06UnityShader介绍

UnityShader介绍 UnityShader的基础ShaderLab UnityShader属性块介绍 Properties {//和public变量一样会显示在Unity的inspector面板上//_MainTex为变量名&#xff0c;在属性里的变量一般会加下划线&#xff0c;来区分参数变量和临时变量//Texture为变量命名//2D为类型&…

微服务学习Day4

文章目录 初始MQ同步通讯和异步通讯MQ常见技术介绍 RabbitMQ快速入门入门案例 SpringAMQP介绍例子WorkQueue模型exchange交换机消息转换器 初始MQ 同步通讯和异步通讯 MQ常见技术介绍 RabbitMQ快速入门 入门案例 SpringAMQP 介绍 例子 WorkQueue模型 exchange交换机 消息转换…

二进制和进制转换

前言 我们经常能听到2进制、8进制、10进制、16进制这样的讲法&#xff0c;那是什么意思呢&#xff1f;其实2进制、8进 制、10进制、16进制是数值的不同表示形式而已。 比如&#xff1a;数值15的各种进制的表示形式&#xff1a; 15的2进制&#xff1a;111115的8进制&#xff1…

最小生成树(习题)

拆地毯 这个就是套用最小生成树的模板&#xff0c;只不过要将sort函数改成从大到小进行排序。然后这个退出条件是只要大于k就退出。 代码如下 #include<iostream> #include<cmath> #include<algorithm> #define N 1009000 using namespace std; int n,m,k…

HarmonyOS—状态管理概述

在前文的描述中&#xff0c;我们构建的页面多为静态界面。如果希望构建一个动态的、有交互的界面&#xff0c;就需要引入“状态”的概念。 图1 效果图 上面的示例中&#xff0c;用户与应用程序的交互触发了文本状态变更&#xff0c;状态变更引起了UI渲染&#xff0c;UI从“He…

【杂谈】裁我?我是研发,我是研发啊!

闲谈 这两年互联网是越来越不太平了&#xff0c;前有国外互联网裁员的妖风四起&#xff0c;后来寒气又传到国内&#xff0c;让我们这群打工人叫苦连天。最近有部电影蛮火的&#xff0c;叫《年会不能停》&#xff0c;感觉跟我前司很相似&#xff0c;不过好像由于今年业绩不太行…

解决LeetCode编译器报错的技巧:正确处理位操作中的数据类型

一天我在leetcode上刷题时&#xff0c;遇到了这样的题目&#xff1a; 随即我写了如下的代码&#xff1a; int convertInteger(int A, int B) {int count 0;int C A ^ B;int flag 1;while(flag){if (C & flag){count;}flag<<1;}return count;} 但LeetCode显示如下…

you-get,一个超强的 Python 库

你好&#xff0c;我是坚持分享干货的 EarlGrey&#xff0c;翻译出版过《Python编程无师自通》、《Python并行计算手册》等技术书籍。 如果我的分享对你有帮助&#xff0c;请关注我&#xff0c;一起向上进击。 现在在线视频超火爆&#xff0c;可是我还是更倾向于将视频下载至本地…

文件上传漏洞--Upload-labs--Pass03--特殊后缀与::$DATA绕过

方法一&#xff1a;特殊后缀绕过&#xff1a; 一、什么是特殊后缀绕过 源代码中的黑名单禁止一系列后缀名 之外的后缀&#xff0c;称之为‘特殊后缀名’&#xff0c;利用其来绕过黑名单&#xff0c;达到上传含有恶意代码的文件的目的。 二、代码审计 接下来对代码逐条拆解进行…

【IO流】32.IO流

IO流 1. IO流1.1 概述1.2 作用1.3 分类1.4 注意事项 1. IO流 IO流&#xff1a;存储和读取数据的解决方案。 I&#xff1a;input O&#xff1a;output 流&#xff1a;像水流一样传输数据 1.1 概述 IO&#xff08;Input/Output&#xff09;流是计算机程序用于与外部设备进行数据…

CSS之margin塌陷

margin塌陷 CSS中的外边距塌陷&#xff08;Margin Collapse&#xff09;问题是指在垂直方向上&#xff0c;当两个或多个块级元素的边距相遇时&#xff0c;它们之间的距离不是它们各自边距的总和&#xff0c;而是其中的最大值。这种现象主要出现在块级元素的上下外边距之间。 &…

【测试】测试用例篇

目 录 一. 设计测试用例的万能公式(六个)二.设计测试用例的具体方法1.等价类2.边界值3.因果图&#xff08;判定表&#xff09;4.场景设计法5.正交法6.错误猜测法 一. 设计测试用例的万能公式(六个) 设计测试用例的万能公式 测试用例的意义是帮助测试人员了解&#xff1a;测什…

智慧公厕适合的场合

智慧公厕是以现代科技手段为基础&#xff0c;融合智能化、信息化和人性化设计的公共厕所&#xff0c;旨在提供更舒适、更便捷的如厕体验。智慧公厕适用于各种场合&#xff0c;包括城市公共厕所、旅游景区公共厕所、美丽乡村公共厕所、机场公共厕所、高铁和火车站公共厕所、高速…