链表高频笔试的OJ题

news2024/11/18 22:31:54

文章目录

一、合并两个有序链表

解题代码

二、反转链表

解题代码

三、分割链表

解题代码 

四、链表的回文结构

解题代码

五、链表相交

解题代码

六、环形链表

解题代码

七、复制带有随机指针的复制链表

解题代码

一、合并两个有序链表

题目来源:牛客网。

题目难度:简单。

题目描述:输入两个递增的链表,单个链表的长度为n,合并这两个链表并使新链表中的节点仍然是递增排序的。

数据范围: 0 <= n <= 1000,-1000≤节点值≤1000,要求:空间复杂度 O(1),时间复杂度 O(n)。

  题解关键思路:

  1. 定义一个哨兵位,易方便操作;
  2. 定义一个尾节点,插入时时刻改变尾节点,方便书写代码;
  3. 比较数据大小,依次尾插即可;
  4. 当有一个链表提前比较插入结束,不要忘记把另一个链表剩下的元素连接起来。

解题代码

struct ListNode* Merge(struct ListNode* pHead1, struct ListNode* pHead2 ) 
{
    if(pHead1==NULL)
    {
        return pHead2;
    }
    if(pHead2==NULL)
    {
        return pHead1;
    }
    struct ListNode* head,* tail;
    head=tail=(struct ListNode*)malloc(sizeof(struct ListNode));
    while(pHead1&&pHead2)
    {
        if(pHead1->val<pHead2->val)
        {
            tail->next=pHead1;
            tail=pHead1;
            pHead1=pHead1->next;
        }
        else
        {
            tail->next=pHead2;
            tail=pHead2;
            pHead2=pHead2->next;
        }
    }  
    if(pHead1)
    {
        tail->next=pHead1;
    }
    if(pHead2)
    {
        tail->next=pHead2;
    }
    struct ListNode* plist=head->next;
    free(head);
    return plist;
}

二、反转链表

题目来源:牛客网。

题目难度:简单。

题目描述:给定一个单链表的头结点pHead(该头节点是有值的,比如在下图,它的val是1),长度为n,反转该链表后,返回新链表的表头。

数据范围: 0≤n≤1000

要求:空间复杂度 O(1) ,时间复杂度O(n) 。

  题解关键思路:

  1. 反转next的指向即可;
  2. 定义三个节点,分别指向空、首节点、第二个节点,从首节点开始反转,依次向后访问。
  3. 也可考虑头插的思路,即定义一个新节点为空,把题目中的链表依次头插入新节点即可。 

解题代码

// struct ListNode* ReverseList(struct ListNode* pHead ) {
//     if (pHead == NULL)
//         return NULL;
//     struct ListNode* n1, *n2, *n3;
//     n1 = NULL;
//     n2 = pHead;
//     n3 = pHead->next;
//     while (n2) {
//         n2->next = n1;
//         n1 = n2;
//         n2 = n3;
//         if (n3)
//             n3 = n3->next;
//     }
//     return n1;
// }
struct ListNode* ReverseList(struct ListNode* pHead )
{
    if(pHead==NULL)
        return NULL;
    struct ListNode* newhead=NULL;
    struct ListNode* cur=pHead;
    struct ListNode* next=cur->next;
    while(cur)
    {
        cur->next=newhead;
        newhead=cur;
        cur=next;
        next=cur->next;
    }
    return newhead;
}

三、分割链表

题目来源:LeetCode。

题目难度:中等。

题目描述:给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。

题解关键思路:

  1. 定义两个新节点,把大于x的和小于x的分成两部分;
  2. 最后连接两部分;
  3. 注意,最后应该将最后一个节点的next置空,防止成回链。

解题代码 

struct ListNode* partition(struct ListNode* head, int x)
{
    struct ListNode* lesshead,*lesstail;
    lesshead=lesstail=(struct ListNode*) malloc(sizeof(struct ListNode));
    lesstail->next=NULL;
    struct ListNode* greaterhead,*greatertail;
    greaterhead=greatertail=(struct ListNode*)malloc(sizeof(struct ListNode));
    greatertail->next=NULL;
    struct ListNode* cur=head;
    while(cur)
    {
        if(cur->val<x)
        {
            lesstail->next=cur;
            lesstail=cur;
        }
        else
        {
            greatertail->next=cur;
            greatertail=cur;
        }
        cur=cur->next;
    }
    lesstail->next=greaterhead->next;
    greatertail->next=NULL;
    struct ListNode* plist=lesshead->next;
    free(lesshead);
    free(greaterhead);
    return plist;
}

四、链表的回文结构

题目来源:LeetCode。

题目难度:简单。

题目描述:给定一个链表的 头节点 head ,请判断其是否为回文链表。如果一个链表是回文,那么链表节点序列从前往后看和从后往前看是相同的。

题解关键思路:

  1. 第一步:找到前半部分尾结点(快慢指针);
  2. 第二步:翻转后半部分(翻转链表);
  3. 第三步:判断是否是回文链表(判断前后两部分的节点是否一致);
  4. 第四步:返回结果。

解题代码

 struct ListNode* Reverse(struct ListNode* head)
 {
    struct ListNode* head1=head;
    struct ListNode *n1,*n2,*n3;
    n1=NULL;
    n2=head1;
    n3=head1->next;
    while(n2)
    {
        n2->next=n1;
        n1=n2;
        n2=n3;
        if(n3)
        n3=n3->next;
    }
    return n1;
 }
bool isPalindrome(struct ListNode* head)
{
    if(head==NULL||head->next==NULL)
    {
        return true;
    }
    struct ListNode* slow,*fast;
    slow=fast=head;
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
    }
    struct ListNode*headRev=Reverse(slow);
    struct ListNode*headBef=head;
    while(headBef&&headRev)
    {
        if(headBef->val!=headRev->val)
        {
            return false;
        }
        else
        {
            headBef=headBef->next;
            headRev=headRev->next;
        }
    }
    return true;
}

五、链表相交

题目来源:LeetCode。

题目难度:简单。

题目描述:给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,返回 null 。

题解关键思路:

  1.  指针 curA 指向 A 链表,指针 curB 指向 B 链表,依次往后遍历;
  2.  先判断curA 和curB的尾是否相同,如果相同,则交叉,如果不同,则不交叉;

  3. 统计两个链表的节点数来判断谁长谁短;

  4. 从头遍历,比较长的链表指针先走两者之差,长度差就消除了如此,再依次同时往后遍历找相同即可。

解题代码

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) 
{
    struct ListNode* curA=headA;
    struct ListNode* curB=headB;
    int countA=1;
    int countB=1;
    while(curA->next||curB->next)
    {
        if(curA->next)
        {
            curA=curA->next;
            countA++;
        }
        if(curB->next)
        {
            curB=curB->next;
            countB++;
        }
    }
    if(curA!=curB)
    {
        return NULL;
    }
    int gap=abs(countA-countB);
    struct ListNode* longlist=headA;
    struct ListNode* shortlist=headB;
    if(countA<countB)
    {
        longlist=headB;
        shortlist=headA;
    }
    while(gap--)
    {
        longlist=longlist->next;
    }
    while(longlist!=shortlist)
    {
        longlist=longlist->next;
        shortlist=shortlist->next;
    }
    return longlist;
}

六、环形链表

题目来源:LeetCode。

题目难度:中等。

题目描述:给定一个链表的头节点  head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。不允许修改 链表。

  

题解关键思路:

  1. 先判断是否为环形链表(快慢指针);
  2. 是环形链表后,找入环点;
  3. 找入环点的方法:一个指针从相遇点开始,另个一指针从头开始,当两个指针相等时即为入环点。 

解题代码

struct ListNode *detectCycle(struct ListNode *head)
{
    struct ListNode *slow=head,*fast=head;
    while(fast&&fast->next)
    {
        slow=slow->next;
        fast=fast->next->next;
        if(slow==fast)
        {
            struct ListNode *meet=fast;
            while(meet!=head)
            {
                meet=meet->next;
                head=head->next;
            }
            return meet;
        }
    }
    return NULL;
}

七、复制带有随机指针的链表

题目来源:LeetCode。

题目难度:中等。

题目描述:给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。构造这个链表的 深拷贝。 深拷贝应该正好由n个全新节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 

例如,如果原链表中有 X 和 Y 两个节点,其中 X.random --> Y 。那么在复制链表中对应的两个节点 x 和 y ,同样有 x.random --> y 。返回复制链表的头节点

  

题解关键思路:

  1. 首先我们可以忽略 random 指针,然后对原链表的每个节点进行复制,并追加到原节点的后面,而后复制 random 指针。

  2. 最后我们把原链表和复制链表拆分出来,并将原链表复原即可。

解题代码

struct Node* copyRandomList(struct Node* head)
{
    struct Node* cur=head;
    //插入相同的节点
    while(cur)
    {
        struct Node* newnode=(struct Node*)malloc(sizeof(struct Node));
        newnode->val=cur->val;
        //插入节点
        newnode->next=cur->next;
        cur->next=newnode;
        cur=newnode->next;
    }
    //复制随机指针
    cur=head;
    while(cur)
    {
        if(cur->random==NULL)
        {
            cur->next->random=NULL;
        }
        else
        {
            cur->next->random=cur->random->next;
        }
        cur=cur->next->next;
    }
    //拆解插入的指针
    cur=head;
    struct Node* newhead=NULL,*newtail=NULL;
    while(cur)
    {
        struct Node*copy=cur->next;
        struct Node*next=copy->next;
        if(newtail==NULL)
        {
            newhead=newtail=copy;
        }
        else
        {
            newtail->next=copy;
            newtail=copy;
        }
        cur->next=next;
        cur=next;
    }
    return newhead;
}

  链表的常见OJ题我们先例举到这里,后续我们会持续更新的哦ovo~

  感谢观看,希望本篇文章会对您有所帮助。

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

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

相关文章

公共用房管理系统有哪些功能和范围?

数图互通房产管理 数图互通公共用房管理系统的管理功能和范围包括: 1、对全部公房进行图形化、电子化、规范、动态化管理。 2、房屋数据定义:可对校区、片区、建筑物、楼层、房间数据进行增删改查&#xff0c;对房间属性数据进行批量修改。 3、档案及多类型附件管理:可对房…

自适应滤波器更新算法-EP1

自适应滤波器更新算法-EP1 自适应滤波器是回声消除系统中非常重要的一个功能模块&#xff0c;而对于自适应滤波器来说&#xff0c;如果更新滤波器系数则是关键所在。本文将介绍几种现有的滤波器更新算法&#xff0c;并附上Matlab测试代码。 1、LMS算法 1.1算法原理 LMS算法即…

【Matplotlib绘制图像大全】(二十二):Matplotlib绘制气泡图

前言 大家好,我是阿光。 本专栏整理了《Matplotlib绘制图像大全》,内包含了各种常见的绘图方法,以及Matplotlib各种内置函数的使用方法,帮助我们快速便捷的绘制出数据图像。 正在更新中~ ✨ 🚨 我的项目环境: 平台:Windows10语言环境:python3.7编译器:PyCharmMatp…

变电站远程监控维护,工程师不用出差跑断腿

电力的稳定产出和供应是社会生产、人民生活的重要保障之一。电力监控系统的作用是对变电站设备和变配电系统的运行状态进行监控和管理&#xff0c;保证安全稳定生产&#xff0c;使得终端用户的用电更加安全&#xff0c;同时企业自身的智能化管理水平也能有所提升。 随着经济和城…

TLS版本及CipherSuites确认及设置

在使用Https&#xff08;AS2、RosettaNet等协议&#xff09;传输协议进行数据传输中&#xff0c;有时会遇到下面这些报错信息&#xff1a; ①276–Error during handshake:接收到的消息异常&#xff0c;或格式不正确。 ②13003&#xff1a;Connot conclude ssl handshake.Caus…

苹果电脑误删文件怎么找回?苹果电脑删了文件能恢复吗?苹果电脑文件删除怎么恢复

现如今&#xff0c;使用苹果电脑的用户越来越多&#xff0c;因为其系统流畅&#xff0c;加上小巧便携&#xff0c;成为了不少用户的不二选择&#xff0c;当然&#xff0c;这些用户也经常会遇到一些问题&#xff0c;比如刚刚一位小伙伴就在给小编吐槽他不小心把苹果电脑上面一些…

【golang】1769. 移动所有球到每个盒子所需的最小操作数---时间复杂度O(N)

有 n 个盒子。给你一个长度为 n 的二进制字符串 boxes &#xff0c;其中 boxes[i] 的值为 ‘0’ 表示第 i 个盒子是 空 的&#xff0c;而 boxes[i] 的值为 ‘1’ 表示盒子里有 一个 小球。 在一步操作中&#xff0c;你可以将 一个 小球从某个盒子移动到一个与之相邻的盒子中。…

微信小程序|使用小程序制作一个世界杯球员识别工具

一、前言二、实现流程三、功能开发四、代码块一、前言 四年一次的世界杯正在卡塔尔进行着&#xff0c;不同的社交圈也在疯狂的刷着世界杯的动态&#xff0c;来自全球各地的三十二支队伍的球员是否让你看的眼花缭乱呢&#xff1f; 当朋友跟你聊起昨晚那场比赛某某某球员的精彩表…

WPS中配置MathType及mathtype实现论文公式一键改大小

目录 0 概述 1 WPS中配置MathType 1.1 步骤1&#xff1a; 1.2 步骤2&#xff1a; 1.3 步骤3&#xff1a; 1.4 步骤4&#xff1a; 1.5 步骤5&#xff1a; 2 mathtype实现论文公式一键改大小 2.1 步骤1&#xff1a; 2.2 步骤2&#xff1a; 2.3 步骤3&#xff1a; 2.4…

大数定律与中心极限定理

给大家讲个有趣的故事 明天概统小测哦可惜了 我的智商还停留在小学时代可惜了&#xff0c;我需要努力学习Physice Doctor in FutureChebyshev 不等式 &#xff08;弱&#xff09;大数定律 Markov 大数定律 Chebyshev 大数定律 独立同分布大数定律 Bernoulli 大数定律 Khinchin …

npm打包整个过程

将自己写的代码包上传到npm&#xff0c; 方便后续下载安装&#xff0c; 步骤如下&#xff1a; 上传 打开npm官方网站&#xff1a; www.npmjs.com; 进行注册 注册需要用户名&#xff0c;密码和邮箱&#xff0c; 当注册完成后需打开邮箱进行验证&#xff08;邮箱不验证无法上传&…

JUC系列(九) CAS 与锁的理解

&#x1f4e3; &#x1f4e3; &#x1f4e3; &#x1f4e2;&#x1f4e2;&#x1f4e2; ☀️☀️你好啊&#xff01;小伙伴&#xff0c;我是小冷。是一个兴趣驱动自学练习两年半的的Java工程师。 &#x1f4d2; 一位十分喜欢将知识分享出来的Java博主⭐️⭐️⭐️&#xff0c;擅…

DZ-51/220【中间继电器】

系列型号 DZ-51中间继电器; DZ-52中间继电器; DZ-53中间继电器; DZ-54中间继电器; JY-16A中间继电器; 一、用途 DZ-51/220;DZ-51/400中间继电器​ (以下简称继电器)用于自动控制装置中&#xff0c;以扩大被控制的电路和提高接通能力。 二、主要技术参数 额定电压&#xff1a;D…

Spring(存储Bean对象五大类注解,获取Bean对象三种注入方式)

目录 1. 先进行配置扫描路径 2. 存储 Bean 对象 ( 添加注解存储 Bean 对象) 2.1 Controller [控制器存储] 2.2 Service [服务存储] 2.3 Repository [仓库存储] 2.4 Configuration [配置存储] 2.5 Component [组件存储] 2.6 五大类注解的作用和关系 2.7 Bean的命名规则…

基于文化算法优化的神经网络预测研究(Matlab代码实现)

目录 1 文化优化算法 2 人工神经网络 3 基于文化算法优化的神经网络预测研究&#xff08;Matlab代码实现&#xff09;运行结果 4 参考文献 5 Matlab代码实现 1 文化优化算法 大自然里的各种生物在生存环境中相互竞争&#xff0c;优胜劣汰&#xff0c;不断进化&#xff0…

股票编程交易接口怎样自动设置止损?

目前随着国内二级股市已处于相对较高的水平&#xff0c;但是对于高净值的用户来说&#xff0c;在量化投资市场上使用股票编程交易接口系统上具有低波动性和自动交易的定量对冲投资模型体系&#xff0c;包括了一些高性价比、大型基金和长期投资的资产品种&#xff0c;所以大家在…

瑞吉外卖-B站最火的新手入门SpringBoot+Mybatis+Redis项目详细教程来了

&#x1f531;项目介绍 项目地址 GitHub&#xff1a;https://github.com/codermast/Takeout-food 对你有用的话&#xff0c;希望能给项目点个Star&#xff0c;非常感谢。 对于项目的任何问题&#xff0c;或者你在本地部署时遇到的无法解决的问题&#xff0c;都可以提交issues…

迭代器模式

文章目录思考迭代器模式1.迭代器模式的本质2.何时选用迭代器模式3.优缺点4.实现手动实现迭代器模式java迭代器模式思考迭代器模式 迭代器模式(Iterator Pattern)是常用的设计模式&#xff0c;属于行为型模式。如果我们的集合元素是用不同的方式实现的&#xff0c;有数组&#…

利用EasyDL制作一个简单的图片识别小项目

主要是利用EasyDL制作一个简单的傻瓜式猫狗图片识别&#xff0c;利用EasyDL&#xff0c;只需要几步简单的点击即可 *主要的步骤&#xff1a; 1.准备数据 2.训练模型 3.部署 4.H5 * 1.首先创建两个文件夹cat和dog分别搜集至少20张以上的猫和狗的图片&#xff08;如果不足20张&…

【High 翻天】Higer-order Networks with Battiston Federico (1)

目录前言高阶网络的表示高阶相互作用的初等表示表示之间的关系总结前言 Ginestra Bianconi 的一篇综述1和一本书2展开的故事。 书还没有开始看&#xff0c;先看看综述吧。综述提供了一个关于超越成对交互的网络新兴领域的概述。 讨论了高阶网络的表示&#xff0c;主要是其中…