牛客CM11 - 链表分割【环形链表雏形】

news2025/7/9 2:59:51

看来真的不能乱割呀~

  • 一、题目描述
  • 二、思路分析
  • 三、代码详解【保姆级教学】
  • 四、环形链表的疑难解惑
  • 五、整体代码展示
  • 六、总结与提炼

一、题目描述

描述

现有一链表的头指针 ListNode* pHead,给一定值x,编写一段代码将所有小于x的结点排在其余结点之前,且不能改变原来的数据顺序,返回重新排列后的链表的头指针。

  • 是的,这题的题目描述总共就这么些,将就着看吧。。。
  • 刷了这么多力扣,转牛客刷刷链表的题,但是这给到题目确实有些【简略】了,你可进网站看看,我有没有骗你

原题传送门

二、思路分析

好,看完题目的描述,我们来分析一下去求解这道题目

  • 好,虽然本题的题目描述有些简略,而且连示例都没有,但这正好是锻炼我们的最佳时机,因为有些公司笔试给你的OJ题目网站也是有可能没有测试案例,这个时候你只能自己去猜测,然后慢慢画图构思,再将自己的思路转化为代码,接下去我们一起来分析一下本题如何求解

  • 首先对于本题的题目描述我们先来理解一下,就是对于给定的一个链表一个一个定值,现在要将比这个【x】要小的数均放在其余结点之前,而且还要保持其相对顺序不变,有些同学可能没有理解题目意思,我们来画个图分析一下

  • 简单地画了张图,题目的意思大概我下面所描述的这样👇

在这里插入图片描述


  • 但是很多同学一定在看了我这张图之后还是没有一个很好的思路,确实,这道题分析起来比较复杂,若是你没有一个巧妙的思路,就很难去得心应手地写出代码,因此需要去想到一个思路,但是光这么做交换真的可以吗,这其实就是你的思维太局限了,为什么题目不给出示例,其实我想也是有它的道理的,放置禁锢了你的思维,上面这个案例只是我随机想的,还有很多的案例,每个案例可能需要使用的方法并不同,因此我们需要进行一个分类讨论
  • 但是在这之前我要先给出你一个整体的题目思路,我的思路是这样的
  • 因为给出的【x】是一个定值,所以可以将这个分割后的链表分为两部分,一部分是【< 5】的,一部分是【>= 5】的,分别将这两部分也定义为链表结构,并且为他们设置头结点,也就是带头的单链表,因为我试了不带头的链表在写起程序来会比较复杂,因为第一次尾插都需要判断头是否为空,所以我后来选择使用带头的单链表进行操作。对于原先的链表,需要定义一个【cur】指针去一一遍历,找到比5小的,就链接在第一个链表后面,找到大于等于5的,就链接在第二个链表后面。

在这里插入图片描述

  • 然后当结点全部链接完成后,将【lessTail】的next指向【greaterHead】的下一个结点,也就是第二个链表的首结点,最后在保存一个第一个链表的首结点返回,得到的就是按照定值分割后的链表

在这里插入图片描述


三、代码详解【保姆级教学】

  • 好,有了这个思路,接下去我们来写代码试试看
  • 首先要开辟四个链表指针,这个没办法
ListNode* lessHead, *lessTail, * greaterHead, *greaterTail;
  • 然后分别对两个链表的头进行的一个动态开辟,申请好一块空间
lessHead = lessTail = (ListNode *)malloc(sizeof(ListNode));
greaterHead = greaterTail = (ListNode *)malloc(sizeof(ListNode));
  • 接着既然是尾插,就要将尾指针的next域置为NULL
lessTail->next = greaterTail->next = NULL;
  • 遍历原先链表的结点指针一定也不能少
ListNode* cur = pHead;
  • 接下去就是这段链表分割与重新链接的过程了,这段逻辑要放到一个循环里,知道原先的链表遍历结束为止,代码很简单,这段逻辑对你来说应该不难
while(cur)
{
    if(cur->val < x){
        lessTail->next = cur;
        lessTail = lessTail->next;
    }else{
        greaterTail->next = cur;
        greaterTail = greaterTail->next;
    }
    cur = cur->next;
}
  • 接下来就是在链接完后将两个链表做一个拼接,也非常直观
lessTail->next = greaterHead->next;
  • 最后,我们去复用一下题目给出的原链表头结点,是其为【lessHead->next】,这样就可以获取到新链表的头,最后的话不要忘了将动态开辟出来的两个头结点指针进行一个释放,养成良好习惯,在牛客里不会出问题,但是呢对于我们日常的开发来说,若是没有在申请内存后及时地释放掉,就会造成【内存泄漏
pHead = lessHead->next;
free(lessHead);
free(greaterHead);
return pHead;
  • 但是从测试用例可以看出,牛客这里是报出了一个叫做【内存超限】的错误,这个的话其实和【超时】比较类似,你可能会想是我们在上面开辟了太多遍历又去申请内存导致的,但是事实却不是这样,想知道的就继续看下去吧❤️

在这里插入图片描述

四、环形链表的疑难解惑

  • 上一小节我们说到了这个【内存超限】的原因,其实并不是因为我们申请的指针变量过多,而是程序的运行导致所占的内存过多,为什么我这样说呢,我通过讲解的这组测试案例运行一下你就知道了
  • 从图中我们可以看到,当我去测试运行一下这组例子的时候,实际的输出结果是很多的数字,但是我们想要的结果是【2 3 4 2 6 7】这6个数字,那其实就可以明白为什么会【内存超限】了,这么多的内容不超才怪呢,就算是【】也把持不住呀,是吧🐮

在这里插入图片描述

  • 那我们就要去分析为什么会产生这种情况?首先就是要去想一下有没有什么特殊情况,总结情况我做了一个罗列,大概就是下面五种,我们刚才进行的判断是后面两种,但是对于有大有小这一种其实还要细分为比较特殊的两种

在这里插入图片描述

  • 首先来看一下这个测试案例,可以看到原先链表的最后一个结点【6】是大于5的,因此放到第二个链表处,而给出的链表的尾结点一定是指向NULL,是一个正常的链表,因此第二个链表的最后一个6也是指向NULL

在这里插入图片描述

  • 这里要给大家说一点的是这两句代码,这也是我刚才忽略的内部循环逻辑,但是现在想起来还是要说一下,对于将当前结点链接到新的链表之后,那么这个【cue->next】会发生变化吗,答案是:不会的
lessTail->next = cur;
greaterTail->next = cur;
  • 所以上面这样图你其实应该理解成这样,虽然你将这个6链接到第二个链表之后了,但是它的【next】指针域还是指向这个【NULL】的,你并没有对这个指针域做修改

在这里插入图片描述


  • 然后我们再来看一个一开始我们讲解的案例
  • 可以看到,对于原先链表的最后一个结点为2,最后将其链接到第一个链表时,修改了它的【next域】,原本2的next应该是指向NULL,现在修改了一下其指向,便指向第二个链表的开头6,但是第二个链表的尾结点7,它的【next域】又是指向谁的呢?没错,它还是指向原先链表中的4,在新链表中也就成了这个样子
  • 这回你应该明白上面在跑这个测试用例的时候为什么会出现很多一模一样重复的数字了吧,其实就是因为新的链表尾还是指向原先的结点,使得这个链表的一些结点形成了一个环,于是在后半部分打印的时候,就变成了一个死循环,从而导致了内存的超限

在这里插入图片描述

  • 这么分析下来,相信你对这个代码改如何修改应该很清楚了吧,没错,就是将第二个链表的尾指针【greaterTial->next = NULL】,这样就可以应对特殊的测试用例了,我们来提交一下试试

  • 过了!!!不得不说,这个声音虽然很重,但是挺多了还是很悦耳的🐶

在这里插入图片描述

五、整体代码展示

展示一下整体的代码,可以看到,我写了一些注释,而且我的思路是很清晰的,对于做题,就是需要将复杂的问题进行一步步地拆分,将一层层的逻辑理清了,这样才能分析到问题的本质!!!

/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) : val(x), next(NULL) {}
};*/
class Partition {
public:
    ListNode* partition(ListNode* pHead, int x) {
        // write code here
        //1.初始化定义结构体指针
        ListNode* lessHead, *lessTail, * greaterHead, *greaterTail;
        //2.为两个链表头分别申请空间
        lessHead = lessTail = (ListNode *)malloc(sizeof(ListNode));
        greaterHead = greaterTail = (ListNode *)malloc(sizeof(ListNode));
        //3.初始化链表尾指针指向
        lessTail->next = greaterTail->next = NULL;
		
        ListNode* cur = pHead;		//遍历原链表的结点指针
        //4.内部遍历分割重组逻辑
        while(cur)
        {
            if(cur->val < x){
                lessTail->next = cur;
                lessTail = lessTail->next;		//链接到另一个链表并不会修改其next指向
            }else{
                greaterTail->next = cur;
                greaterTail = greaterTail->next;
            }
            cur = cur->next;
        }
        //5.链接两个链表
        lessTail->next = greaterHead->next;
        greaterTail->next = NULL;		//记住特殊情况,将尾结点指针置为NULL
		//6.获取新链表的头
        pHead = lessHead->next;
        free(lessHead);
        free(greaterHead);		//及时释放申请的内存,放置内存泄漏
        return pHead;
    }
};

六、总结与提炼

  • 最后我们来总结一下本文所介绍的内容,本文讲解的是一道牛客网中的题目:【链表分割】,对于本题与大多数题目不同的一点首先是做起来很吃力,因为没有示例,而且在报出运行错误的时候会有一大堆的数字,若是太急便很难去静下心来仔细分析。
  • 而且本题的难点在于对于特殊情况的指针,需要做一个特殊的修改,否则就会像我们看到的那样,造成【内存超限】,这个报错在力扣上是没有的,对于牛客来说,它的整体完善度虽然没有力扣那么高,题库和测试用例也没有力扣来的全,但是对于本题,我觉得很好地提升了分析算法题的能力。我们不能一直呆在温室里,也要有阳光的照射才能真正成长

以上就是本文所要描述的所有内容,感谢您对本文的观看,如有疑问请于评论区留言或者私信我都可以🍀

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

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

相关文章

数据库-范式

目录 完全函数依赖部分函数依赖传递函数依赖码主属性非主属性第一范式(1NF)第二范式(2NF)第三范式(3NF)例题完全函数依赖 每一个属性都有用,缺一个都不能决定。 部分函数依赖 部分属性用不到,也可以决定 传递函数依赖

抽象类和(上)

大家好&#xff0c;又见面了&#xff0c;今天和大家浅谈一下抽象类 抽象类存在的意义就是被继承 抽象类 &#x1f437;1.抽象类的定义 &#x1f431;‍&#x1f680;2.抽象类的语法 &#x1f49a;3.抽象类的概念 &#x1f680;4.抽象类的作用 1.抽象类的概念 什么是 好…

[附源码]java毕业设计基于个性化的汽车购买推荐系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

如何在Ubuntu 22.04上安装Linux 内核 6.0?

内核是任何基于 Linux 的操作系统的核心部分&#xff0c;它充当计算机系统软件和硬件之间的桥梁&#xff0c;还提供用户和应用程序与计算机交互所需的接口。内核提供了许多功能&#xff0c;包括进程调度、资源分配、设备管理、中断处理、内存管理和进程。 在撰写本文时&#x…

轻松学会jQuery选择器的用法

文章目录⛳️ 选择器✨ 属性选择器✨ 包含选择器✨ 位置选择器✨ 过滤选择器✨ 反向选择器⛳️ 快速投票⛳️ 选择器 本篇重点讲解jQuery中丰富的选择器&#xff0c;以及他们的基本用法。CSS的选择器均可以用jQuery的$进行选择&#xff0c;部分浏览器对CSS3的选择器支持不全&am…

大道至简,凯里亚德酒店成为酒店投资圈万众瞩目的“新”星

作为近年酒店市场的热门领域&#xff0c;中端酒店行业的发展一直颇受关注。随之而来的就是中端酒店品牌的不断增加&#xff0c;以及中端商旅、度假型酒店规模的不断扩大&#xff0c;经行业资深人士分析&#xff0c;未来中端酒店将成为酒店市场的主力产品。鉴于市场的发展趋势&a…

Netty中的缓存Bytebuf

首先我们来明确一下Buffer&#xff08;缓存&#xff09; JavaNIO中的Buffer、Netty中的Buffer、Netty中的Bytebuf这是3个不同的类&#xff0c;但实现的内容和完成的功能几乎一致&#xff0c;最原始的是JavaNIO中的Buffer实现&#xff0c;最先进的是Netty中Bytebuf的实现&#x…

10 分钟, 带你彻底掌握 SQL 多表查询

1.前言 多表查询&#xff0c;也称为多表连接查询&#xff1b;作为关系型数据库最主要的查询方式&#xff0c;在日常工作中被广泛使用 常见的多表查询操作包含&#xff1a;子查询、内连接、左外连接、右外连接、完全连接、交叉连接 本篇文章将利用一个实例逐一介绍这些操作 …

【华为OD机试真题 python】 太阳能板最大面积【2022 Q4 | 100分】

■ 题目描述 给航天器一侧加装长方形或正方形的太阳能板&#xff08;图中的红色斜线区域&#xff09;&#xff0c;需要先安装两个支柱&#xff08;图中的黑色竖条&#xff09;&#xff0c;再在支柱的中间部分固定太阳能板。 但航天器不同位置的支柱长度不同&#xff0c;太阳能…

做一名既有宽度也有深度的测试!

一名好的测试人员&#xff0c;在工作中&#xff0c;不仅要做到有宽度更要有深度&#xff01; 何为宽度&#xff1f;测试用例的覆盖面更广更全。 测试人员设计测试用例的时候可以分为这几种类型&#xff1a; 一&#xff1a;将prd的需求描述copy到测试用例。 二&#xff1a;细…

Java线程安全与对象头结构信息

文章目录一 线程安全问题1.1 什么是线程安全问题&#xff1f;1.2 自增运算真的线程安全吗&#xff1f;1.3 Synchronized锁表现三种形势&#xff1f;1.3.1 synchronized同步方法1.3.2 synchronized同步代码块1.3.3 synchronized静态方法1.3.4 总结二 Java对象结构与内置锁2.1 Ja…

浏览器自动化利器Selenium IDE使用指南

文章目录前言一、安装及界面1.1 安装1.2 界面二、常用命令2.1 通用2.2 表单2.3 流程控制三、常用操作3.1 命令操作3.2 js脚本3.3 录制3.4 导出四、实际操作例子4.1 红黑树插入可视化4.2 github下载参考前言 Selenium 是一个浏览器自动化框架&#xff0c;专门为 W3C WebDriver …

创龙AD+全志T3 TL7606I模块测试

上一篇&#xff1a;创龙AD全志T3 ad_display 开发案例(2) 前 言 本文主要介绍基于全志科技T3(ARM Cortex-A7)处理器的8/16通道AD采集开发案例&#xff0c;使用核芯互联CL1606/CL1616AD芯片&#xff0c;亦适用于ADI AD7606/AD7616。CL1606/CL1616与AD7606/AD7616软硬件兼容。 …

力扣(LeetCode)775. 全局倒置与局部倒置(C++)

模拟 理解题&#xff0c;全局倒置就是不相邻的逆序对&#xff0c;局部倒置就是相邻的逆序对。提示中给出&#xff0c;0<nums[i]<n0 < nums[i] < n0<nums[i]<n &#xff0c;其中 nnums.lengthn nums.lengthnnums.length , numsnumsnums 中的所有整数 互不相…

什么是 rektguy NFT系列?

rektguy 系列是一组闪烁着霓虹灯颜色的饮酒骷髅 该项目背后的团队没有提出路线图或分支项目 艺术家 OSF 已经在 NFT 生态系统中拥有一个成熟的粉丝群体 rektguy NFT系列由 8,814 个 NFT 组成&#xff0c;展示了穿着连帽衫、用瓶子喝水的骷髅。这些人物由深黑色背景上闪烁的霓…

[论文阅读] 颜色迁移-EM概率分割的局部颜色迁移

[论文阅读] 颜色迁移-EM概率分割的局部颜色迁移 文章: Local Color Transfer via Probabilistic Segmentation by Expectation-Maximization,[paper][code(未公开)] 本文目的为: 图像局部颜色迁移. 1-符号说明 在进行本文算法原理说明之前, 先对一些英文缩写进行简单说明: …

一次nacos 导致的 CPU 飙高问题

序 今天下午突然 出现 测试环境 cpu飙高&#xff0c;干到了 60%&#xff0c;其他项目 响应时间明显变长。。。有点吓人&#xff0c;不想背锅 项目背景 出问题的项目是 需要连接各个不同nacos 和不同的 namespace 进行对应操作的 一个项目&#xff0c;对nacos的操作都是httpC…

JavaScript break 、 continue和return 语句介绍

目录 一、Break 1、介绍 2、代码&#xff1a; 3、示例&#xff1a; 二、Continue 1、介绍 2、代码 3、示例 三、break 、continue总结&#xff1a; 代码 示例 四、Return 1、简介 2、语法&#xff1a; 3、代码 4、示例 五、return、break、continue总结 1、re…

02【MyBatis框架的CRUD】

二、MyBatis框架的CRUD 重新搭建一个新的MyBatis环境&#xff0c;进行MyBatis的CRUD测试&#xff1b; 参考&#xff1a;01【MyBatis-快速入门】 2.1 新增 2.1.1 dao接口 package com.dfbz.dao;/*** author lscl* version 1.0* intro:*/ import com.dfbz.entity.Emp;public i…

秒杀系统设计(微服分布式)

流程图(分布式) 例子 现场要卖1000件下面这个婴儿纸尿裤&#xff0c;根据以往这样秒杀活动的数据经验来看&#xff0c;目测来抢这100件纸尿裤的人足足有10万人 问题 高并发 秒杀的特点就是这样时间极短、 瞬间用户量大。 正常的店铺营销都是用极低的价格配合上短信、APP的…