剑指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(数据结构与算法面试题精讲)》。在如今竞争激烈的技术求职环境下,算法能力已成为前端开发岗位笔试考核的关键要点。通过深入钻研这一系列算法题,大家能够系统地积累算法知识和解题经验。每一道题目的分析与解答过程,都像是一把钥匙,为大家打开一扇通往高效编程思维的大门,帮助大家逐步提升自己在数据结构运用、算法设计与优化等方面的能力。
    无论是即将踏入职场的应届毕业生,还是想要进一步提升自己技术水平的在职开发者,掌握扎实的算法知识都是提升竞争力的有力武器。希望大家能跟随我的步伐,在这个系列中不断学习、不断进步,为即将到来的前端笔试做好充分准备,顺利拿下心仪的工作机会!快来订阅吧,让我们一起开启这段算法学习之旅!

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

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

相关文章

【BFT帝国】20250409更新PBFT总结

2411 2411 2411 Zhang G R, Pan F, Mao Y H, et al. Reaching Consensus in the Byzantine Empire: A Comprehensive Review of BFT Consensus Algorithms[J]. ACM COMPUTING SURVEYS, 2024,56(5).出版时间: MAY 2024 索引时间&#xff08;可被引用&#xff09;: 240412 被引:…

前端用用jsonp的方式解决跨域问题

前端用用jsonp的方式解决跨域问题 前端用用jsonp的方式解决跨域问题 前端用用jsonp的方式解决跨域问题限制与缺点&#xff1a;前端后端测试使用示例 限制与缺点&#xff1a; 不安全、只能使用get方式、后台需要相应jsonp方式的传参 前端 function jsonp(obj) {// 动态生成唯…

MySQL详解最新的官方备份方式Clone Plugin

一、Clone Plugin的动态安装 install plugin clone soname mysql_clone.so;select plugin_name,plugin_status from information_schema.plugins where plugin_name clone; 二、Clone Plugin配置持久化 在 MySQL 配置文件my.cnf中添加以下内容&#xff0c;确保插件在 MySQL …

解决python manage.py shell ModuleNotFoundError: No module named xxx

报错如下&#xff1a; python manage.py shellTraceback (most recent call last):File "/Users/z/Documents/project/c/manage.py", line 10, in <module>execute_from_command_line(sys.argv)File "/Users/z/.virtualenvs/c/lib/python3.12/site-packa…

鸿蒙NEXT开发资源工具类(ArkTs)

import { AppUtil } from ./AppUtil; import { StrUtil } from ./StrUtil; import { resourceManager } from kit.LocalizationKit;/*** 资源工具类。* 提供访问应用资源的能力&#xff0c;包括布尔值、数字、字符串等资源的获取。** author 鸿蒙布道师* since 2025/04/08*/ ex…

css使用mix-blend-mode的值difference实现内容和父节点反色

1. 使用场景 往往开发过程中&#xff0c;经常遇到产品说你这个背景图和文字颜色太接近了&#xff0c;能不能适配下背景图&#xff0c;让用户能够看清具体内容是啥。 这么说吧&#xff0c;这种需求场景非常合理&#xff0c;因为你做开发就是要给用户一个交代&#xff0c;给他们…

el-input 中 select 方法使用报错:属性“select”在类型“HTMLElement”上不存在

要解决该错误&#xff0c;需明确指定元素类型为 HTMLInputElement&#xff0c;因为 select() 方法属于输入元素。 步骤解释&#xff1a; 类型断言&#xff1a;使用 as HTMLInputElement 将元素类型断言为输入元素。 可选链操作符&#xff1a;保持 ?. 避免元素为 null 时出错…

Mybatis Plus与SpringBoot的集成

Mybatis Plus与SpringBoot的集成 1.引入Maven 依赖2.配置application.yml文件3.创建实体类4.分页插件5.逻辑删除功能6.忽略特定字段7.自动填充 1.引入Maven 依赖 提前创建好一个SpringBoot项目&#xff0c;然后在项目中引入MyBatis Plus依赖 <dependency><groupId&g…

大数据学习(104)-clickhouse与hdfs

&#x1f34b;&#x1f34b;大数据学习&#x1f34b;&#x1f34b; &#x1f525;系列专栏&#xff1a; &#x1f451;哲学语录: 用力所能及&#xff0c;改变世界。 &#x1f496;如果觉得博主的文章还不错的话&#xff0c;请点赞&#x1f44d;收藏⭐️留言&#x1f4dd;支持一…

【简历全景认知2】电子化时代对简历形式的降维打击:从A4纸到ATS的生存游戏

一、当简历遇上数字洪流:传统形式的式微 在1990年代,一份排版精美的纸质简历还能让HR眼前一亮;但今天,超过75%的 Fortune 500 企业使用ATS(Applicant Tracking System)进行初筛,未优化的简历可能在5秒内就会沦为数字废土。这种变迁本质上符合「技术接纳生命周期」理论—…

esp32cam -> 服务器 | 手机 -> 服务器 直接服务器传输图片

服务器先下载python &#xff1a; 一、Python环境搭建&#xff08;CentOS/Ubuntu通用&#xff09; 一条一条执行 安装基础依赖 # CentOS sudo yum install gcc openssl-devel bzip2-devel libffi-devel zlib-devel # Ubuntu sudo apt update && sudo apt install b…

SeaTunnel系列之:Apache SeaTunnel编译和安装

Apache SeaTunnel编译 Prepare编译克隆源代码本地安装子项目从源代码构建 SeaTunnel构建子模块安装 JetBrains IDEA Scala 插件安装 JetBrains IDEA Lombok 插件代码风格运行简单示例不仅如此 安装下载 SeaTunnel 发布包下载连接器插件从源代码构建 SeaTunnel 运行 SeaTunnel 在…

JavaScript/React中,...(三个连续的点)被称为 扩展运算符(Spread Operator) 或 剩余运算符(Rest Operator)

const processOrder (order) > {const tax order.total * 0.1;const finalAmount order.total tax;return { ...order, tax, finalAmount }; }; 解释一下&#xff0c;特别&#xff1a;...?在JavaScript/React中&#xff0c;...&#xff08;三个连续的点&#xff09;被称…

FRP的proxies只是建立通道,相当于建立与服务器沟通的不同通道而不是直接将路由器与服务器云端沟通

没有更好的办法了吗&#xff0c;我看frpc.toml的里面可以设置两个proxies那我esp32的监听端口设置在frpc.toml里面它不也能跟云服务器建立联系吗&#xff0c;比如远程与本地端口都配置为5112那云服务器接收到的5112访问会以frp配置的本地端口5112转发到frp客户端的路由器&#…

#在docker中启动mysql之类的容器时,没有挂载的数据...在后期怎么把数据导出外部

如果要导出 Docker 容器内的 整个目录&#xff08;包含所有文件及子目录&#xff09;&#xff0c;可以使用以下几种方法&#xff1a; 方法 1&#xff1a;使用 docker cp 直接复制目录到宿主机 适用场景&#xff1a;容器正在运行或已停止&#xff08;但未删除&#xff09;。 命…

Java的JDK、JRE、JVM关系与作用

Java的JDK、JRE、JVM关系与作用 java中的JDK、JRE和JVM是三个核心组件&#xff0c;各自承担不同角色&#xff0c;且存在层级依赖关系 1. JVM&#xff08;Java Virtual Machine&#xff0c;Java虚拟机&#xff09; 是什么&#xff1a; JVM是虚拟的计算机&#xff0c;能够执行…

C++学习之套接字并发服务器

目录 1.昨天套接字服务器的弊端 2.如何通过多进程方式实现服务器并发 3.多进程服务器-1 4.多进程服务器-2 5.多进程版程序-回收子进程被信号中断的处理 6.多线程版TCP服务处理思路 7.多线程并发服务器编写 8.为什么不能把文件描述符地址传到子线程中 9.多线程程序测试 …

机器学习新范式:Kubernetes + Kubeflow,解锁模型训练与部署的高效密码

一、Kubernetes在机器学习模型训练与部署中的作用 Kubernetes作为一个强大的容器编排平台&#xff0c;为机器学习模型的训练与部署提供了以下核心支持&#xff1a; 分布式训练支持&#xff1a;Kubernetes能够自动化部署和管理PyTorch等机器学习框架的分布式训练任务。通过利用…

动态科技感html导航网站源码

源码介绍 动态科技感html导航网站源码&#xff0c;这个设计完美呈现了科幻电影中的未来科技界面效果&#xff0c;适合展示技术类项目或作为个人作品集的入口页面&#xff0c;自适应手机。 修改卡片中的链接指向你实际的HTML文件可以根据需要调整卡片内容、图标和颜色要添加更…

数字内容智能推荐优化策略

个性化推荐算法构建路径 构建高效数字内容体验的推荐系统&#xff0c;需以多源数据融合为基础框架。首先通过用户画像建模整合人口属性、行为轨迹及兴趣标签&#xff0c;结合协同过滤与深度学习算法建立内容关联矩阵。在此基础上&#xff0c;引入上下文感知机制&#xff0c;动…