链表面试题及其解析

1.返回倒数第k个节点

实现一种算法,找出单向链表中倒数第 k 个节点。返回该节点的值。

示例:

输入: 1->2->3->4->5 和 k = 2
输出: 4

说明:

给定的 k 保证是有效的。

1.1快慢指针

即慢指针一次走一步,快指针一次走两步,两个指针从链表起始位置开始运行,如果链表带环则一定会在环中相遇,否则快指针先走到链表的末尾

1.2解题代码

/*
快慢指针法 fast, slow, 首先让fast先走k步,然后fast,slow同时走,fast走到末尾时,slow走到倒数第k个节点。
*/
class Solution {
public:ListNode* FindKthToTail(ListNode* pListHead, unsigned int k) {struct ListNode* slow = pListHead;struct ListNode* fast = slow;while(k--){if(fast)fast = fast->next;elsereturn NULL;}while(fast){slow = slow->next;fast = fast->next;}return slow;}
};

 2.链表的回文结构

对于一个链表,请设计一个时间复杂度为O(n),额外空间复杂度为O(1)的算法,判断其是否为回文结构。给定一个链表的头指针A,请返回一个bool值,代表其是否为回文结构。保证链表长度小于等于900。

测试样例:

1->2->2->1
返回:true

2.1解题思路

可以先找到中间节点,然后把后半部分逆置,在对前后两部分一一对比,如果节点的值全部相同,则即为回文。

2.2解题代码

class PalindromeList {
public:bool chkPalindrome(ListNode* A) {if (A == NULL || A->next == NULL)return true;ListNode* slow, *fast, *prev, *cur, *nxt;slow = fast = A;//找到中间节点while (fast && fast->next){slow = slow->next;fast = fast->next->next;}prev = NULL;//后半部分逆置cur = slow;while (cur){nxt = cur->next;cur->next = prev;prev = cur;cur = nxt;}//逐点比对while (A && prev){if (A->val != prev->val)return false;A = A->next;prev = prev->next;}return true;}
};

2.3此题的另一种解法

可以先把链表中的元素值全部保存在数组中,然后再判断数组是否回文,不建议使用这种解法,因为如果没有告诉链表最大长度,则不能同此解法。

class PalindromeList {
public:bool chkPalindrome(ListNode* A) {// write code hereint a[900] = {0};ListNode* cur = A;int n = 0;//保存链表元素while(cur){a[n++] = cur->val;cur = cur->next;}//判断数组是否为回文结构int begin = 0, end = n-1;while(begin < end){if(a[begin] != a[end])return false;++begin;--end;}return true;}
};

3.相交链表

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

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

3.1解题思路

可以先计算出两个链表的长度,让长的链表先走相差的长度,然后两个链表同时走,直到遇到相同的节点,即为第一个公共节点。

3.2解题代码

struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB) {int lenA = 0, lenB = 0;struct ListNode* curA = headA, *curB = headB;//计算链表长度while(curA) {++lenA;curA = curA->next;}while(curB) {++lenB;curB = curB->next;}int gap = abs(lenA-lenB);struct ListNode* longList = headA, *shortList = headB;if(lenA < lenB) {longList = headB;shortList = headA;}//让长链表先走几步while(gap--){longList = longList->next;}//两个链表同时走,直到遇到相同的节点while(longList && shortList){if(longList == shortList) {return longList;}else {longList = longList->next;shortList = shortList->next;}}return NULL;
}

4.随机链表的复制

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

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

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

返回复制链表的头节点。

用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:

  • val:一个表示 Node.val 的整数。
  • random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为  null 。

你的代码  接受原链表的头节点 head 作为传入参数。

4.1解题思路

1.拷贝链表的每一个节点,拷贝的节点先链接到被拷贝节点的后面

2.复制随机指针的链接:拷贝节点的随机指针指向被拷贝节点随机指针的下一个位置

3.拆解链表,把拷贝的链表从原链表中拆解出来

4.2解题代码

class Solution {
public:Node* copyRandomList(Node* head) {// 1.拷贝链表,并插入到原节点的后面Node* cur = head;while(cur){Node* next = cur->next;Node* copy = (Node*)malloc(sizeof(Node));copy->val = cur->val;// 插入cur->next = copy;copy->next = next;// 迭代往下走cur = next;}// 2.置拷贝节点的randomcur = head;while(cur){Node* copy = cur->next;if(cur->random != NULL)copy->random = cur->random->next;elsecopy->random = NULL;cur = copy->next;}// 3.解拷贝节点,链接拷贝节点Node* copyHead = NULL, *copyTail = NULL;cur = head;while(cur){Node* copy = cur->next;Node* next = copy->next;// copy解下来尾插if(copyTail == NULL){copyHead = copyTail = copy;}else{   copyTail->next = copy;copyTail = copy;}cur->next = next;cur = next;}return copyHead;}
};

5.环形链表|

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

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

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

5.1解题思路

定义快慢指针fast,slow, 如果链表确实有环,fast指针一定会在环内追上slow指针。

5.2解题代码

typedef struct ListNode Node;
bool hasCycle(struct ListNode *head) {Node* slow = head;Node* fast = head;while(fast && fast->next){slow = slow->next;fast = fast->next->next;if(slow == fast)return true;}return false;
}

6. 环形链表||

6.1解题思路

如果链表存在环,则fast和slow会在环内相遇,定义相遇点到入口点的距离为X,定义环的长度为C,定义头到入口的距离为L,fast在slow进入环之后一圈内追上slow,

则会得知: slow所走的步数为:L + X fast所走的步数为:L + X + N * C

并且fast所走的步数为slow的两倍,故: 2*(L + X) = L + X + N * C

即: L = N * C - X 所以从相遇点开始slow继续走,让一个指针从头开始走,相遇点即为入口节点 

6.2解题代码

typedef struct ListNode Node;
struct ListNode *detectCycle(struct ListNode *head) {Node* slow = head;Node* fast = head;while(fast && fast->next){slow = slow->next;fast = fast->next->next;//走到相遇点if(slow == fast){// 求环的入口点Node* meet = slow;Node* start = head;while(meet != start){meet = meet->next;start = start->next;}return meet;}}return NULL;
}

7.拓展快慢指针

7.1快指针每次两步,慢指针每次一步

假设链表带环,两个指针最后都会进入环,快指针先进环,慢指针后进环。当慢指针刚进环时,可
能就和快指针相遇了,最差情况下两个指针之间的距离刚好就是环的长度。此时,两个指针每移动
一次,之间的距离就缩小一步,不会出现每次刚好是套圈的情况,因此:在满指针走到一圈之前,
快指针肯定是可以追上慢指针的,即相遇。

7.2 快指针走3步or4步....n步呢

假设快指针一次走3步,慢指针一次走两步

快慢指针之间的距离变化:

当N为偶数的时候:N-3    N-6  ...............  6    3   0 

当N为奇数的时候:N-3    N-6 ................  5    2    -1(当为-1时,则快慢指针刚好擦肩而过,此时距离变为C-1)

如若C-1为偶数,那么快慢指针相遇,如若C-1为奇数,那么快慢指针不会相遇

所以说:N为奇数,C为为偶数,则不可能相遇

是否存在此情况? 

快指针一次走3步,慢指针一次走1步,此时快指针肯定先进环,慢指针后来才进环。

环的长度为C,环距头结点的距离是L,当slow刚进入环的时候与fast的距离是N

在判环时,快慢指针相遇是所走的路径长度:

slow刚进环时,有:

fast:L+n*C+C-N                       slow: L

注意:1.当慢指针进入环时,快指针可能已经在环中绕了几圈了,n至少为1 

2.慢指针进入环之后,快指针肯定会在慢指针走一圈之内追上慢指针

因为:慢指针进入环后,快慢指针之间的距离最多就是环的长度,而两个指针在移动时。距离都在缩减。

fast每次走三步,所以路程是慢指针的三倍,所以有:

3L= L+n*C+C-N   ------>>>2L = (n-1)C-N

等式左边是2L,永远是偶数,所以等式右边也必须是偶数,N为奇数,C为偶数,偶数乘以任意数也是偶数,则偶数 - 奇数不等一偶数,则不存在此情况

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

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

相关文章

关于Windows登录密码的思考题

1. windows登录的明文密码&#xff0c;存储过程是怎么样的&#xff0c;密文存在哪个文件下&#xff0c;该文件是否可以打开&#xff0c;并且查看到密文 在Windows系统中&#xff0c;密码通常以哈希值的形式存储在注册表中的SAM文件中。SAM文件位于C:\Windows\System32\config\S…

简化Transformer模型,以更少的参数实现更快的训练速度

在深度学习领域&#xff0c;Transformer模型因其卓越的性能而广受欢迎&#xff0c;但其复杂的架构也带来了训练时间长和参数数量多的挑战。ETH Zurich的研究人员Bobby He和Thomas Hofmann在最新研究中提出了一种简化的Transformer模型&#xff0c;通过移除一些非必要的组件&…

FP16、BF16、INT8、INT4精度模型加载所需显存以及硬件适配的分析

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…

基于SSM SpringBoot vue宾馆网上预订综合业务服务系统

基于SSM SpringBoot vue宾馆网上预订综合业务服务系统 系统功能 首页 图片轮播 宾馆信息 饮食美食 休闲娱乐 新闻资讯 论坛 留言板 登录注册 个人中心 后台管理 登录注册 个人中心 用户管理 客房登记管理 客房调整管理 休闲娱乐管理 类型信息管理 论坛管理 系统管理 新闻资讯…

文心一言 VS 讯飞星火 VS chatgpt (251)-- 算法导论18.2 4题

四、假设关键字 {1&#xff0c;2&#xff0c;…&#xff0c;n} 被插入一棵最小度数为 2 的空 B 树中&#xff0c;那么最终的B树有多少个结点&#xff1f;如果要写代码&#xff0c;请用go语言。 文心一言&#xff1a; B树&#xff08;B-tree&#xff09;是一种自平衡的树&…

2024年钉钉群直播回放如何永久保存

工具我已经打包好了&#xff0c;有需要的自己取一下 链接&#xff1a;百度网盘 请输入提取码 提取码&#xff1a;1234 --来自百度网盘超级会员V10的分享 1.首先解压好我给大家准备好的压缩包 2.再把逍遥一仙下载器压缩包也解压一下 3.打开逍遥一仙下载器文件夹里面的M3U8…

2022蓝桥杯国赛

题目描述&#xff1a; 思路&#xff1a; 题主用了两个方法&#xff0c;一个是三维数组&#xff0c;1到2022个数可以当成编号&#xff0c;f[i][j][k]表示前i个数选了j个数总和为k&#xff0c;存在是否选择第i个数的问题&#xff0c;选择第i个数为f[i-1][j-1][k-i];没有选择第i个…

计算机网络实验——学习记录六(TCP协议流量控制分析)

1. nc -d 5 -lv 4499 > 10K.1 其中&#xff1a; &#xff08;1&#xff09;-d 5 表示建立连接之后&#xff0c;延迟5秒再读取数据&#xff1b; &#xff08;2&#xff09;> 10K.1 表示将输出重定向到文件10K.1中&#xff1b; 2. 零窗口通知报文 3. 窗口探测报文

Gitea 上传用户签名

在 Gitea 的用户管理部分&#xff0c;有一个 SSH 和 GPG 的选项。 单击这个选项&#xff0c;可以在选项上添加 Key。 Key 的来源 如是 Windows 的用户&#xff0c;可以选择 Kleopatra 这个软件。 通过这个软件生成的 Key 的界面中有一个导出功能。 单击这个导出&#xff0c;…

Redis 实战3

系列文章目录 本文将从跳跃表的实现、整数集合来展开 Redis 实战 Ⅲ 系列文章目录跳跃表的实现跳跃表节点层 前进指针跨度 整数集合的实现升级升级的好处提升灵活性节约内存 降级整数集合 API总结 跳跃表的实现 Redis 的跳跃表由 redis.h/zskiplistNode 和 redis.h/zskiplist…

nginx--压缩https证书favicon.iconginx隐藏版本号 去掉nginxopenSSL

压缩功能 简介 Nginx⽀持对指定类型的⽂件进行压缩然后再传输给客户端&#xff0c;而且压缩还可以设置压缩比例&#xff0c;压缩后的文件大小将比源文件显著变小&#xff0c;这样有助于降低出口带宽的利用率&#xff0c;降低企业的IT支出&#xff0c;不过会占用相应的CPU资源…

FreeRTOS学习——FreeR TOS队列(下)

本篇文章记录我学习FreeRTOS的队列的相关知识&#xff0c;在此记录分享一下&#xff0c;希望我的分享对你有所帮助。 FreeRTOS学习——FreeRTOS队列&#xff08;上&#xff09;-CSDN博客 一、FreeRTOS队列的创建 &#xff08;一&#xff09;、函数原型 在使用队列之前必须先创…

【Linux 系统】进程信号 -- 详解

⚪前言 注意&#xff1a;进程间通信中的信号量跟下面要讲的信号没有任何关系。 一、从不同角度理解信号 1、生活角度的信号 你在网上买了很多件商品&#xff0c;在等待不同商品快递的到来。但即便快递没有到来&#xff0c;你也知道快递来临时&#xff0c;你该怎么处理快递&a…

Java | Leetcode Java题解之第63题不同路径II

题目&#xff1a; 题解&#xff1a; class Solution {public int uniquePathsWithObstacles(int[][] obstacleGrid) {int n obstacleGrid.length, m obstacleGrid[0].length;int[] f new int[m];f[0] obstacleGrid[0][0] 0 ? 1 : 0;for (int i 0; i < n; i) {for (i…

Python根据预设txt生成“你画我猜”题目PPT(素拓活动小工具)

Python根据预设txt生成“你画我猜”题目PPT&#xff08;素拓活动小工具&#xff09; 场景来源 去年单位内部的一次素拓活动&#xff0c;分工负责策划设置其中的“你画我猜”环节&#xff0c;网络上搜集到题目文字后&#xff0c;想着如何快速做成对应一页一页的PPT。第一时间想…

数据结构与算法-双向链表

1.简介 在使用带头节点的单向链表查找时查找的方向只能是一个方向&#xff0c;而双向链表可以向前或向后查找。例如单向链表只能查到一个节点的下一个节点&#xff0c;但是双向链表不仅可以查到下一个节点&#xff0c;还可以查到上一个节点。 在删除节点时&#xff0c;单向链…

AI-数学-高中-47导数与几何意义

原作者视频&#xff1a;【导数】【考点精华】7导数与几何意义考点解析&#xff08;基础&#xff09;_哔哩哔哩_bilibili 该点处切点的斜率 该点处导函数的值 示例1&#xff1a; 导数问题解决最常用方法&#xff1a;参数分离&#xff0c;在左边函数有解的值域范围内。 示例2&…

数组的定义及实现

文章目录 前言一、定义二、抽象数据类型定义三、顺序存储四、具体实现总结 前言 T_T此专栏用于记录数据结构及算法的&#xff08;痛苦&#xff09;学习历程&#xff0c;便于日后复习&#xff08;这种事情不要啊&#xff09;。所用教材为《数据结构 C语言版 第2版》严蔚敏。 一、…

21世纪世界最具影响力的华人颜廷利:乱与净之中的汉字智慧

人类离不开‘卵’字&#xff0c; 众生离不开‘乱’&#xff08;与‘卵’同音&#xff09;字&#xff1b; 生命离不开‘精’字&#xff0c; 升命离不开‘净’&#xff08;与‘精’同音&#xff09;字…&#xff08;升命学说&#xff09; 21世纪东方哲学家思想家、科学家、当代中…

量化研究---pywencai问财数据的使用,提供源代码

文章链接 量化研究---pywencai问财数据的使用,提供源代码 (qq.com) pywencai是一个强大的第三方库库&#xff0c;开源的源代码&#xff0c;但是教程比较少&#xff0c;我简单的写一个教程结合我的使用&#xff0c;也开源直接访问我网页 网页http://120.78.132.143:8023/wencai…