【手撕数据结构】链表面试题进阶

news2024/9/22 19:33:41

目录

  • 相交链表
  • 环形链表
    • 扩展问题
  • 环形链表||
    • 原理
  • 随机链表的复制

相交链表

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

图示两个链表在节点 c1 开始相交:

在这里插入图片描述
在这里插入图片描述
思路:
1.想要判断两个链表相交的话,就得找到他的相交节点,但是如果两个链表都从自己起始位置开始找的话如:
在这里插入图片描述
在这里插入图片描述
2.求长短链表的差值,让长链表走差值步
如果其中一个链表比另一个链表长就始终会比短的链表少走一步,这里我们不妨算出两个链表的长度,求他们的差值,让长的链表先走差值步,再长链表和短链表一起走就行了。

在这里插入图片描述
在这里插入图片描述
这样就会遇到相交节点了

3.若链表不相交,则不会遇到相交节点,最后会遍历到各自NULL.

 typedef struct ListNode ListNode;
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {
    int n1 = 0;
    int n2 = 0;
    ListNode* pcur1 = headA,*pcur2 = headB;
    while(pcur1)
    {
        n1++;
        pcur1 = pcur1->next;
    }
    while(pcur2)
    {
        n2++;
        pcur2 = pcur2->next;
    }
    int gap = abs(n1-n2);	//绝对值,有可能n1比n2小
    ListNode* ShortList = headA;
    ListNode* LongList = headB;
    if(n1 >n2)
    {
        LongList = headA;
        ShortList = headB;
    }
    while(gap--)
    {
        LongList = LongList->next;
    }
    while(ShortList && LongList)
    {
        if(LongList ==ShortList)
        {
            return LongList;
        }
        ShortList = ShortList->next;
        LongList = LongList->next;
    }
    return NULL;
}

注意:我们判断谁是长链表可以直接通过他们的长度谁大来判断

环形链表

给你一个链表的头节点 head ,判断链表中是否有环。

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。注意:pos 不作为参数进行传递 。仅仅是为了标识链表的实际情况。

如果链表中存在环 ,则返回 true 。 否则,返回 false 。

在这里插入图片描述
思路:
这道题思路有点不好想,直说就是用到快慢指针,两个指针都从头结点开始遍历,慢指针走一步,快指针走两步,最坏这两个指针一定会在一个节点相遇.

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
为什么一定会相遇呢:
在这里插入图片描述
在这里插入图片描述
每次fast和slow走的时候,fast走两步,slow走一步,他们的距离都缩小1,n-1直到n-n=0就相遇了

扩展问题

这里我们再深入一下问题,如果快指针一次走3步,4步,n步呢?还一定会相遇吗?

这里我们先看快指针一次走3步的情况:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这里原本是fast追slow,现在变成了slow追fast,这就出现了套圈。

他们每次距离:N,N-2,N-4,N-6.这里如果N是偶数的话会相遇,但如果N为奇数如上例就会出现套圈。此时套圈后他们之间的距离为:C - 1
那么套圈后他们还有可能相遇吗?
我们这里证明N为奇数套圈的情况:
(1)套圈后的距离(C-1为偶数会相遇
(2)套圈后的距离(C-1)为奇数不相遇
下面我们证明C-1为奇数不相遇的情况

这里我们再来看一个图:
在这里插入图片描述
L为入环的距离,N为fast和slow之间的距离,那么fast走的距离就是C-N(这里设环的周长为C)
slow走的距离:L
fast走的距离:L+XC+C-N 这里xc表示有可能fast已经走了很多圈,加上L如果L很长的话最好加上。
又因为3slow=fast
有3L=L+XC+C-N
化简:2L=(X+1)C-N
证明C-1为奇数不相遇的情况
左边:偶数*任何数=偶数 右边:这里N已经为奇数,那么只有奇数-奇数为偶数
也就是(X+1)C是一个奇数,
c

c-1是奇数,那么C是一个偶数,偶数乘任何数都等于偶数,不满足等式的性质(偶数=偶数)(这里C是偶数就是偶数-奇数,上面说了是奇数-奇数)。

所以这里不存在C-1为奇数的情况,所以他们一定会相遇。

环形链表||

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

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

不允许修改 链表。
在这里插入图片描述

思路:如果一个指针从头结点开始一步一步走,一个指针从相遇点一步一步走,那么他们一定会在入环节点相遇。

typedef struct ListNode ListNode;
struct ListNode *detectCycle(struct ListNode *head) {
    ListNode* slow,*fast;
    slow = fast = head;
    while(fast && fast->next)
    {
        //找到相遇点
        slow = slow->next;
        fast = fast->next->next;
        if(slow == fast)
        {   //进了这里链表一定有环
            //从头结点和相遇点开始同时一步一步遍历一定会在入环节点相遇
            ListNode* pcur = head;
            while(pcur != fast)
            {
                pcur = pcur->next;
                fast = fast->next;
            }
            return pcur;
        }
    }
    return NULL;
}

原理

在这里插入图片描述
就是证明:L=C-X
注意上面的N是周期

随机链表的复制

给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。

构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。

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

返回复制链表的头节点。

注意:

  • 深拷贝就是新建一个链表复制过来。
  • 复制链表中的指针都不应指向原链表中的节点 。
    在这里插入图片描述
    或许有人认为,简单嘛,直接创建一个新链表,定义一个指针指向原链表开始遍历一个一个复制到新链表,遍历到NULL为止。如果是链表的指针只有一个那这样是对的
    在这里插入图片描述
    但是我们很明显的看出来,这个链表不光有next指针,还有一个random指针,并且这个指针是随机的,可以指向自己或者链表中的任何一个节点还有NULL,所以我们单纯的复制是行不通的

思路:
1.将复制的节点尾插到旧链表每个对应节点的后面,并且把旧链表的next指针指向新链表的对应节点。
‘如:
在这里插入图片描述

’原节点1不再指向原原节点2,而是指向新节点1

2.设置random指针,这就体现了我们为什么把新链表的节点尾插到旧链表中相对应的节点的好处,我们可以直接通过变量旧链表->random->next指针找到新链表中的random指针的位置。

在这里插入图片描述

3.将旧链表和新链表之间断开

在这里插入图片描述

typedef struct Node Node;
Node* BuyNode(int x)
{
    Node* newnode = (Node*)malloc(sizeof(Node));
    newnode->val = x;
    newnode->next = newnode->random = NULL;
    return newnode;
}
void AddNode(Node* phead)
{
    Node* pcur = phead;
    while(pcur)
    {
        Node* Next = pcur->next;
        //创建新节点,尾插到pcur
        Node* newnode = BuyNode(pcur->val);
        pcur->next = newnode;
        newnode->next = Next;
        pcur = Next;  
    }
}
struct Node* copyRandomList(struct Node* head) {
    if(head == NULL)
    {
        return NULL;
    }
    //复制原链表的节点并且将他们之间进行连接
    AddNode(head);
    //设置random指针
    Node* pcur = head;
    while(pcur)
    {
        Node* copy = pcur->next;
        if(pcur->random != NULL)
        {
            copy->random = pcur->random->next;
        }
       pcur = copy->next;
    }
    //断开原链表和旧链表的连接
    pcur = head;
    Node* NewHead,*NewTail;
    NewHead = NewTail = pcur->next;
    while(pcur->next->next)
    {
        pcur = pcur->next->next;
        NewTail->next = pcur->next;
        NewTail = NewTail->next;
    }
    return NewHead;
}

注意第一个节点的random指针指向NULL,但是我们创建节点的时候就已经把random指针设置NULL不需要单独处理

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

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

相关文章

Centos7.6升级Nginx到nginx-1.27.0

Centos7.6升级Nginx到nginx-1.27.0 简介 升级过程 常见问题 简介 Nginx 更新到了1.27.0,为了系统的安全性将进行服务升级 升级过程 一、Nginx的卸载 升级前需要先卸载以前安装的版本 1、yum的卸载 > yum remove nginx同时还需要手动删除配置文件和日志文…

sqli-labs靶场——第三关

1、判断注入类型 ?id1和?id2-1的页面不一样 2、判断闭合类型 http://127.0.0.1/sqli-labs/Less-3/?id1)and 11 -- 页面正常 http://127.0.0.1/sqli-labs/Less-3/?id1)and 12 -- 页面变化 3、order by查看有几列 http://127.0.0.1/sqli-labs/Less-3/?id1)order by 4 --页面…

vue3+ts+pinia+vant-项目搭建

1.pnpm介绍 npm和pnpm都是JavaScript的包管理工具,用于自动化安装、配置、更新和卸载npm包依赖。 pnpm节省了大量的磁盘空间并提高了安装速度:使用一个内容寻址的文件存储方式,如果多个项目使用相同的包版本,pnpm会存储单个副本…

LABVIEW2016安装教程完整版安装图文教程、注册下载方法

大家好,今天分享下LABVIEW2016安装步骤,同样的安装前请大家务必退出杀毒软件,安装路径千万不要出现中文或其他特殊符号,否则都会导致安装失败的,跟着教程来安装都会安装成功的,如果你遇到了安装问题&#x…

springboot整合mybatis-plus(数据层Dao/Mapper测试)

第一部分:创建springboot文件 第一步:打开软件,点击file,点击new 然后选择module,在右侧选择springboot 第二步:选择配置和JDK以及java版本 ①选择maven类型 ②选择JDK1.8版本 ③选择java8版本 ④选择j…

破解监控难题,局域网电脑监控软件哪家强?

现在的环境,企业要想茁壮成长,员工的高效工作那可是关键中的关键。但不少老板都发现了一个头疼的问题,员工上班老是偷懒,这可怎么行?今天,就来给大家详细说道说道几款出色的局域网电脑监控软件,…

使用Nginx Proxy Manager配置Halo的反向代理和申请 SSL 证书

本文介绍Nginx Proxy Manager配置Halo的反向代理和申请 SSL 证书,如需要了解Halo 2的安装,参考 如何在Linux云服务器上通过Docker Compose部署安装Halo,搭建个人博客网站?。 文章目录 安装Nginx Proxy ManagerNginx Proxy Manager…

人工智能会越来越闭源——对话东北大学副教授王言治 | Open AGI Forum

作者 | Annie Xu 责编、采访 | Echo Tang 出品丨GOSIM 开源创新汇 在读期间研究方向为并不“火”的模式识别与深度学习,毕业却刚好踩上人工智能计算研究的风口……来自美国东北大学的王言治副教授深耕深度学习与大模型,前瞻性地探索大模型的本地化部署…

服务器并发模型

服务器: 单循环服务器:服务器在同一时刻只能响应一个客户端的请求 并发服务器模型:服务器在同一时刻可以响应多个客户端的请求 UDP:无连接 TCP:有连接 1.多进程 资源空间消耗大 效率低 2.多线程 相…

yolo格式数据集之地面道路病害检测4种数据集已划分好|可以直接使用|yolov5|v6|v7|v8|v9|v10通用

yolo格式数据集之地面道路病害检测4种数据集已划分好|可以直接使用|yolov5|v6|v7|v8|v9|v10通用 本数据为地面道路病害检测检测数据集,数据集数量如下: 总共有:8535张 训练集:5981张 验证集:1768张 测试集:786 类别数量…

机器学习之心一区级 | Matlab实现SMA-Transformer-LSTM多变量回归预测(黏菌算法优化)

机器学习之心一区级 | Matlab实现SMA-Transformer-LSTM多变量回归预测(黏菌算法优化) 目录 机器学习之心一区级 | Matlab实现SMA-Transformer-LSTM多变量回归预测(黏菌算法优化)效果一览基本介绍程序设计参考资料 效果一览 基本介…

leetcode 矩阵专题——java实现

73. 矩阵置零 给定一个 m x n 的矩阵,如果一个元素为 0 ,则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 输入:matrix [[1,1,1],[1,0,1],[1,1,1]] 输出:[[1,0,1],[0,0,0],[1,0,1]] 关键在于:一次扫描全表…

Java高级Day18-集合

62.集合 之前保存多个数据元素使用数组,但数组有以下缺点: 长度开始必须指定,指定后不可修改 保存的必须为同一类型的元素 使用数组进行增加/删除元素的代码比较麻烦 集合 可以动态的保存任意多个对象 提供了一系列方便操作对象的方法 …

基于IDEA+Mysql+SpringBoot开发的健康运动系统

基于IDEAMysqlSpringBoot开发的健康运动系统 项目介绍💁🏻 http://localhost:8088/login.html 账号密码 xpf 123 在当前快节奏的社会生活中,随着人们健康意识的不断提升,个人健康管理已成为社会关注的焦点。随着科技的飞速发展&am…

反爬虫限制:有哪些方法可以保护网络爬虫不被限制?

目前,爬虫已经成为互联网数据获取最主流的方式。但为了保证爬虫顺利采集数据,需要防范网站的反爬虫机制,降低IP被限制的风险,这样才能提高爬虫工作的效率。那么,如何防止网络爬虫被限制呢?下面介绍几种有效…

在亚马逊云科技AWS上利用RAG搭建一个向量库云原生AI对话机器人

简介: 小李哥将继续每天介绍一个基于亚马逊云科技AWS云计算平台的全球前沿AI技术解决方案,帮助大家快速了解国际上最热门的云计算平台亚马逊云科技AWS AI最佳实践,并应用到自己的日常工作里。 本次介绍的是如何利用亚马逊云科技一系列热门A…

昇思25天学习打卡营第16天|Diffusion扩散模型,DCGAN生成漫画头像

Diffusion扩散模型 关于扩散模型(Diffusion Models)有很多种理解,本文的介绍是基于denoising diffusion probabilistic model (DDPM),DDPM已经在(无)条件图像/音频/视频生成领域取得…

7.30 模拟赛总结 [神奇性质]+[线段树二分]

复盘 7:40 成功开题,艾教场 看 T1,感觉很神奇,但看数据范围没有开到 1 e 9 1e9 1e9 之类的,应该是得怎么搜一下;T2 发现做过原题,秒了;T3 第一眼没看懂题,推样例始终不理解其中的…