剑指Offer(数据结构与算法面试题精讲)C++版——day8
剑指Offer(数据结构与算法面试题精讲)C++版——day8
- 题目一:链表中环的入口节点
- 题目二:两个链表的第1个重合节点
- 题目三:反转链表
- 附录:源码gitee仓库
题目一:链表中环的入口节点


这道题的有如下三个关键点:
(1)判断链表中是否存在环;
(2)找出环的长度;
(3)快慢指针遍历链表得到相遇节点,该相遇节点即为环入口。
首先对于环的存在性判断,可以使用快慢指针,一开始让front指针和end指针都指向第一个节点,接下来慢指针每次向前移动1个节点,快节点每次向前移动2个节点,这样快指针每次都会比慢指针多走1个节点,如果链表中存在环,那么存在一种情况,快指针比慢指针多走k*n,其中k表示一个正整数,n为环的长度。
接下来便是找出环的长度了,在第一次快慢指针相遇之后,让快慢指针按照之前的方式接着向前走,最后快慢指针会第二次相遇,此时便有快指针比慢指针多走的长度就是链表中环长。
最后,调整依次快慢指针的开始位置,快慢指针都设置成第一个节点,接着快指针向前走环长,然后快慢指针一起向前走,下一次相遇说明便找到了入口节点了。最终得到如下代码:
# include <iostream>
# include <algorithm>
using namespace std;
struct linkNode {int data;linkNode * next;linkNode(int val):data(val),next(nullptr) {}
};
typedef linkNode * linkList;linkList createLinkList(int arr[],int len) {//使用空头链表linkList head=new linkNode(0),q=head;for(int i=0; i<len; ++i) {linkNode * p=new linkNode(arr[i]);q->next=p;q=p;}q->next=nullptr;return head;
}void mockCircle(linkList head) {linkList p=head;linkNode * q=nullptr,*last=nullptr;while(p!=nullptr) {if(p->data==3) {q=p;}if(p->next==nullptr) {last=p;}p=p->next;}last->next=q;
}linkNode* findCircleEnter(linkList head) {linkNode *front=head->next,*end=head->next;int count=1;while(front!=nullptr&&end!=nullptr&&front!=end) {front=front->next;if(end->next) {end=end->next->next;} else {end!=nullptr;}}if(end==nullptr) {return nullptr;} else {front=front->next;end=end->next->next;while(front!=end) {front=front->next;end=end->next->next;count++;}cout<<"输出环长:"<<count<<endl;front=head->next;end=head->next;while(count--) {end=end->next;}while(front!=end) {front=front->next;end=end->next;}return end;}
}int main() {int arr[]= {1,2,3,4,5,6};linkList head= createLinkList(arr,6);mockCircle(head);cout<<"输出入口节点的值:"<<findCircleEnter(head)->data<<endl;return 0;
}

补充说明,实际代码应该没有这里长,通常算法只需要写findCircleEnter函数,但是为了方便去模拟这个查找过程,这里根据图例构造了带环模拟链表(带有空头链表)。这里的时间复杂度也比较好,站在front的角度,一开始为了得到环的长度,只需要遍历一次链表,然后找入口节点,总和来看最多遍历两次链表,因此总的时间复杂度为O(n)。
题目二:两个链表的第1个重合节点


依稀记得这是考研408中的一道真题,相较于前面的题目而言,这道题的难度稍显简单。这道题的解题关键在于统一起点,然后让两个链表一起向后遍历。具体的操作步骤是,首先分别对两个链表的长度进行一次统计,这样便能清晰知晓两个链表长度的差异。接着,使用两个指针,让它们各自指向两个链表的第一个节点,此时,根据之前统计得到的链表长度,让长度较长的链表的指针先走gap个节点。例如,若长链表的长度为m,短链表的长度为n,那么gap的值就是两者的差值,即n-m。通过这样的方式,使得两个链表的指针处于相对统一的起始位置,以便后续的遍历操作。基于上述思路,于是便可以得到如下的代码来实现相应的功能。
# include <iostream>
# include <algorithm>
using namespace std;
struct linkNode {int data;linkNode * next;linkNode(int val):data(val),next(nullptr) {}
};
typedef linkNode * linkList;linkList createLinkList(int arr[],int len) {//使用空头链表linkList head=new linkNode(0),q=head;for(int i=0; i<len; ++i) {linkNode * p=new linkNode(arr[i]);q->next=p;q=p;}q->next=nullptr;return head;
}
void mockCircle(linkList head1,linkList head2) {linkList p1=head1->next,p2=head2->next;linkNode * q=nullptr;while(p1!=nullptr) {if(p1->data==4) {q=p1;}p1=p1->next;}while(p2->next!=nullptr) {p2=p2->next;}p2->next=q;
}linkNode* findCommon(linkList head1,linkList head2) {int count1=0,count2=0,gap=0;linkNode * p1=head1, *p2=head2,*p=head1->next,*q=head2->next;while(p1->next) {//统计head1链表长度 p1=p1->next;count1++;}while(p2->next) {//统计head2链表长度p2=p2->next;count2++;}while(count1>count2) {//拉齐链表起点 p=p->next;count1--;}while(count2>count1) {q=q->next;count2--;}while(p!=q){p=p->next;q=q->next;}return q;
}int main() {int arr1[]= {1,2,3,4,5,6};int arr2[]= {7,8};linkList head1= createLinkList(arr1,6);linkList head2= createLinkList(arr2,2);mockCircle(head1,head2);cout<<"输出公共节点对应的值:"<<findCommon(head1,head2)->data<<endl;return 0;
}

同样的,实际编码的时候只需要写findCommon即可。
题目三:反转链表


在数据结构与算法的学习和考察中,链表相关的题目一直是重点内容,而本题基本上算得上是链表系列的必考题。因为链表反转操作在实际的编程场景,如操作系统底层数据处理、图形渲染中的节点顺序调整等方面经常会被使用到。对于这道题,其解题的一个非常关键的思路是,将指针pre初始化为null。这样做的目的在于为后续链表节点指针方向的改变提供一个起始参照。在每次循环过程中,巧妙地改变指针的指向,从而逐步实现链表的反转。每一次指针方向的调整,都是对链表原有结构的一次重塑,通过这种循环操作,最终能够将整个链表的顺序反转过来。最终得到的代码如下:
# include <iostream>
# include <algorithm>
using namespace std;
struct linkNode {int data;linkNode * next;linkNode(int val):data(val),next(nullptr) {}
};
typedef linkNode * linkList;linkList createLinkList(int arr[],int len) {//使用空头链表linkList head=new linkNode(0),q=head;for(int i=0; i<len; ++i) {linkNode * p=new linkNode(arr[i]);q->next=p;q=p;}q->next=nullptr;return head;
}void printLinkList(linkList head) {linkList p=head->next;while(p!=nullptr) {cout<<p->data<<" ";p=p->next;}
}
void reverseList(linkList head) {linkNode * pre=nullptr,*cur=head->next,*next=nullptr,*last=nullptr;while(cur) {if(!cur->next) {//因为存在空头,所以在真实元素反转后,需要让头指向最后一个节点last=cur;}next=cur->next;cur->next=pre;pre=cur;cur=next;}head->next=last;
}int main() {int arr1[]= {1,2,3,4,5};linkList head= createLinkList(arr1,5);reverseList(head);cout<<"输出反转之后的链表:";printLinkList(head);return 0;
}

附录:源码gitee仓库
考虑到有些算法需要模拟数据,如果全部放进来代码显得过长,不利于聚焦在算法的核心思路上。于是把所有的代码整理到了开源仓库上,如果想要看详细模拟数据,可在开源仓库自取:【凌空暗羽/剑指offer-C++版手写代码】。
我是【Jerry说前后端】,本系列精心挑选的算法题目全部基于经典的《剑指 Offer(数据结构与算法面试题精讲)》。在如今竞争激烈的技术求职环境下,算法能力已成为前端开发岗位笔试考核的关键要点。通过深入钻研这一系列算法题,大家能够系统地积累算法知识和解题经验。每一道题目的分析与解答过程,都像是一把钥匙,为大家打开一扇通往高效编程思维的大门,帮助大家逐步提升自己在数据结构运用、算法设计与优化等方面的能力。
无论是即将踏入职场的应届毕业生,还是想要进一步提升自己技术水平的在职开发者,掌握扎实的算法知识都是提升竞争力的有力武器。希望大家能跟随我的步伐,在这个系列中不断学习、不断进步,为即将到来的前端笔试做好充分准备,顺利拿下心仪的工作机会!快来订阅吧,让我们一起开启这段算法学习之旅!
相关文章:
剑指Offer(数据结构与算法面试题精讲)C++版——day8
剑指Offer(数据结构与算法面试题精讲)C版——day8 题目一:链表中环的入口节点题目二:两个链表的第1个重合节点题目三:反转链表附录:源码gitee仓库 题目一:链表中环的入口节点 这道题的有如下三个…...
【Qt】QxOrm:下载、安装、使用
1、下载源码 github地址:https://github.com/QxOrm/QxOrm 稳定版本下载:https://github.com/QxOrm/QxOrm/releases/tag/1.5.0 2、编译源码 QxOrm支持cmake编译(CMakeLists.txt)、Qt pro工程编译(QxOrm.pro) 以 QxOrm.pro 为例,编译生成的库,没有在 build-QxOrm-1.5…...
CISCO组建RIP V2路由网络
1.实验准备: 2.具体配置: 2.1根据分配好的IP地址配置静态IP: 2.1.1PC配置: PC0: PC1: PC2: 2.1.2路由器配置: R0: Router>en Router#conf t Enter configuration…...
【数学建模】(智能优化算法)鲸鱼优化算法(Whale Optimization Algorithm)详解与应用
鲸鱼优化算法(Whale Optimization Algorithm)详解与应用 文章目录 鲸鱼优化算法(Whale Optimization Algorithm)详解与应用1. 引言2. 算法原理2.1 生物学基础2.2 数学模型[^3]1. 包围猎物阶段2. 气泡网攻击(螺旋更新)3. 随机搜索猎物(全局探索…...
【深度洞察】解码饮料行业破局点:场景革命
当东鹏特饮以 “大瓶装 防尘盖” 精准解决货车司机的场景化需求,当农夫山泉通过 “冷藏版东方树叶” 打开年轻白领的早餐场景 —— 这些现象级案例背后,是饮料行业底层逻辑的深刻变革:真正的市场增量,藏在对消费场景的极致拆解中…...
工业科学级天文相机:跨界融合的高精密成像解决方案
随着国内科技的快速发展,工业相机领域正悄然兴起一场"天文级"的技术革命。这类兼具工业设备可靠性与天文观测精度的特殊相机,正在半导体制造、天文观测、空间探测等领域开辟新的应用疆域。其核心技术突破不仅体现在传感器性能的提升࿰…...
回文日期2
#include <bits/stdc.h> using namespace std; bool huiwen(int date) {int tempdate;int r0;while(temp>0){rr*10temp%10;temp/10;}return dater; }int main() {// 请在此输入您的代码int n,m;cin>>n>>m;int tempfn/100,tempem/100;int yearfn/10000,mon…...
Ubuntu搭建Pytorch环境
Ubuntu搭建Pytorch环境 例如:第一章 Python 机器学习入门之pandas的使用 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 Ubuntu搭建Pytorch环境前言一、Anaconda二、Cuda1.安装流程2、环境变量&#…...
图书管理系统(Python)
运行结果: 源代码: # 定义一个图书类 class Book: def __init__(self, title, author, isbn): self.title title self.author author self.isbn isbn def show_info(self): print(f"{self.title},{self.author},{self.isbn}") # 图书列表…...
大模型本地部署系列(3) Ollama部署QwQ[阿里云通义千问]
大家好,我是AI研究者, 今天教大家部署 一个阿里云通义千问大模型。 QwQ大模型简介 QwQ是由阿里云通义千问(Qwen)团队推出的开源推理大模型,专注于提升AI在数学、编程和复杂逻辑推理方面的能力。其核心特点包括&#x…...
操作系统 4.1-I/O与显示器
外设工作起来 操作系统让外设工作的基本原理和过程,具体来说,它概括了以下几个关键步骤: 发出指令:操作系统通过向控制器中的寄存器发送指令来启动外设的工作。这些指令通常是通过I/O指令(如out指令)来实现…...
前端-Vue3
1. Vue3简介 2020年9月18日,Vue.js发布版3.0版本,代号:One Piece(n 经历了:4800次提交、40个RFC、600次PR、300贡献者 官方发版地址:Release v3.0.0 One Piece vuejs/core 截止2023年10月,最…...
Facebook账号类型一览
对于跨境出海从业者来说,Facebook是必不可少的内容营销和广告投放平台。针对Facebook的营销策略和发挥空间都很丰富,因此了解Facebook账号的类型、特点、适用场景和相关工具还是很有用的。 一、账号类型及特点 1.小黑号 无主页、无好友、无历史操作&am…...
Kotlin 通用请求接口设计:灵活处理多样化参数
在 Kotlin 中设计一个通用的 ControlParams 类来处理不同的控制参数,有几种常见的方法:方案1:使用密封类(Sealed Class) sealed class ControlParamsdata class LightControlParams(val brightness: Int,val color: S…...
Java学习手册:Java基本语法与数据类型
Java语言以其简洁明了的语法和强大的数据类型系统而闻名。掌握Java的基本语法和数据类型是成为一名合格Java开发者的第一步。本文将深入探讨Java的基本语法结构和数据类型,帮助读者打下坚实的基础。 Java的基本语法 Java语言的语法设计简洁而强大,强调…...
通过扣子平台将数据写入飞书多维表格
目录 1.1 创建飞书开放平台应用 1.2 创建飞书多维表格 1.3 创建扣子平台插件 1.1 创建飞书开放平台应用 1.1.1 打开地址:飞书开放平台,点击创建应用 注:商店应用需要申请ISV资质,填写企业主体信息,个人的话&#x…...
C++-Mongoose(2)-https-server-openssl
OpenSSL生成HTTPS自签名证书 - 简书 1.Openssl windowsubuntu下载http://www.openssl.vip/download1.VS2019编译OpenSSL 2.VS2019编译第一个OpenSSL项目 1.ubuntu编译OpenSSL 3.0 2.编写第一个OpenSSL 1.windows下编译OpenSSL 安装vs2019 perl nasm安装activePerl…...
【GDB】调试程序的基本命令和用法(Qt程序为例)
1. 引言 GDB(GNU Debugger)是一个强大的命令行调试工具,它可以帮助开发者在程序运行时查找和修复错误。当调试Qt程序时,GDB同样适用,并且能够帮助开发者定位诸如数组越界挂死等复杂问题。 2. 基本命令 2.1 启动GDB …...
力扣DAY46-50 | 热100 | 二叉树:展开为链表、pre+inorder构建、路径总和、最近公共祖先、最大路径和
前言 中等 、困难 √,越来越有手感了,二叉树done! 二叉树展开为链表 我的题解 前序遍历树,当遇到左子树为空时,栈里pop节点,取右子树接到左子树位置,同时断开该右子树与父节点的连接&#x…...
服务器DNS失效
服务器异常 xx.t.RequestException: java.net.UnknownHostException: test.ac.xxxx.cn现象分析 本地测试正常,说明域名本身无问题。服务器 DNS 解析异常,导致 UnknownHostException。**服务器可正常解析 ****baidu.com**,说明网络正常&#…...
用excel做九乘九乘法表
公式: IF($A2>B 1 , 1, 1,A2 & “" & B$1 & “” & $A2B$1,”")...
企业数据安全如何保障?深度解析AIGC系统源码本地化部署
—从数据加密到权限管控,构建企业级AI安全防线 企业AIGC面临的5大数据安全风险 1. 数据出境违规 典型场景: 使用ChatGPT处理客户信息 → 数据经美国服务器中转 → 违反《个人信息保护法》第38条某金融公司因通过Midjourney生成宣传图,导致产…...
《妖风》-来自DeepSeek
《妖风》 周明揉了揉酸胀的眼睛,电脑屏幕上的Excel表格已经模糊成一片绿色的小格子。窗外,三月的阳光懒洋洋地洒进来,带着春天特有的那种让人昏昏欲睡的温暖。办公室里中央空调的嗡嗡声像是一首催眠曲,他的眼皮越来越重。 "…...
鬼泣:蓄力攻击
文章目录 蓄力攻击:有两个动作,蓄力时触发蓄力动作,攻击时触发攻击动作1.蓄力动作2.攻击动作 浮空上挑1.蓄力对齐位置 2.攻击 下劈斩1.蓄力对齐位置 2.攻击 beiwuf debug事件分发器发送:调用发送器即可发送消息接收:绑…...
企业指标设计方法指南
该文档聚焦企业指标设计方法,适用于企业中负责战略规划、业务运营、数据分析、指标管理等相关工作的人员,如企业高管、部门经理、数据分析师等。 主要内容围绕指标设计展开:首先指出指标设计面临的困境,包括权责不清、口径不统一、缺乏标准规范、报表体系混乱、指标…...
CSS学习02 动态列数表格开发,解决多组数据布局与边框重合问题
概要 在前端开发中,表格常用于展示结构化数据。当数据组的字段数量不统一时(如有的行包含 3 组数据,有的行包含 2 组或 1 组),传统固定列数的表格会出现结构错位、边框重合等问题。本文通过 HTML/CSS 规范方法&#x…...
加载js/mjs模块时服务器返回的 MIME 类型不对导致模块被拒绝执行
浏览器报错 Failed to load module script: The server responded with a non-JavaScript MIME type of "text/html". Strict MIME type checking is enforced for module scripts per HTML spec.Understand this errorAI 核心问题 浏览器加载模块脚本(如…...
大唐杯省赛安排来了!还有7天,该如何准备?
(一)赛道一:工程实践赛 1、理论赛阶段由参赛队伍使用两台电脑分别登录学唐平台作答,仿真实践赛阶段为参赛队伍共用一台电脑,以竞赛小组方式共同作答(按照报名顺序,用第1选手账号登录仿真平台)。最终统计理…...
iframe学习与应用场景指南
一、iframe核心原理与学习路径 1. 嵌套网站的本质原理 技术特性: • 浏览器为每个iframe创建独立的window对象和DOM环境 • 资源独立加载:子页面拥有自己的CSS/JS/Cookie作用域 • 跨域限制:同源策略下无法直接访问DOM(需CORS或…...
WebGL数学手记:矩阵基础
一、矩阵的定义 矩阵,数学术语。在数学中,矩阵(Matrix)是一个按照长方阵列排列的复数或实数集合。 1.英文发音(Matrix) Matrix的发音类似于中文的[美吹克斯],知道它的发音。方便后期看教程时…...
