链上相遇,节点之间的悸动与牵连

在这里插入图片描述

公主请阅

  • 1. 返回倒数第 k 个节点
    • 1.1 题目说明
    • 1.2 题目分析
    • 1.3 解法一代码以及解释
    • 1.3 解法二代码以及解释
  • 2.相交链表
    • 2.1 题目说明
      • 示例 1
      • 示例 2
      • 示例 3
    • 2.2 题目分析
    • 2.3 代码部分
    • 2.4 代码分析

1. 返回倒数第 k 个节点

在这里插入图片描述

题目传送门


1.1 题目说明

题目名称:
面试题 02.02. 返回倒数第k个节点

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

注意:
本题相对原题稍作改动。

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

说明:
给定的k保证是有效的。


1.2 题目分析

这个题的话需要我们将倒数第k个节点进行返回,那么我们先想到的是什么呢?怎么找打倒数第k个节点呢?
解法一
那么这个时候我就想着将这个链表先逆置了,然后遍历k次我们就可以找到原先链表的倒数第k个节点了
这个是一种解法

解法二
要解决这个问题,我们可以使用 双指针(又称为 快慢指针)来找到链表中的倒数第 k 个节点。具体思路如下:

  1. 初始化两个指针,都指向链表的头节点。

    • 快指针 fast
    • 慢指针 slow
  2. 移动快指针,先让 fast 指针前进 k 步。

  3. 同时移动快慢指针,当 fast 指针到达链表末尾时,slow 指针的位置就是倒数第 k 个节点的位置。

详细步骤:

  1. 定义 fastslow 两个指针,初始时都指向链表头部。
  2. fast 先走 k 步,这样在之后的同时移动中,fastslow 之间的距离始终保持 k
  3. 然后同时移动 fastslow,每次 fast 向后移动一格,直到 fast 到达链表的末尾。
  4. 此时,slow 就是倒数第 k 个节点。

那么下面我们会将两个解决方案的代码呈现出来的


1.3 解法一代码以及解释

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*/int kthToLast(struct ListNode* head, int k)
{struct ListNode*prev=NULL;struct ListNode*cur=head;while(cur!=NULL)//遍历整个链表,将链表反转了{struct ListNode*tmp=cur->next;cur->next=prev;prev=cur;cur=tmp;}//到这里prev就是反转链表的头结点了while(--k){prev=prev->next;}return prev->val;
}//先将链表进行反转的操作,然后我们就可以直接利用循环来找到第k个节点了

先定义两个指针

-prev指向当前节点的前一个节点,初始化为NULL

  • cur指向当前节点,初始化为头结点

然后我们使用while循环进行遍历操作,直到我们遍历到尾节点我们就结束了
我们先定义一个指针tmp将当前节点的下一个节点进行保存了
然后我们现在开始将相邻的两个节点的指向进行改变的操作了
我们让当前节点的下个节点指向我们的prev,然后对prev这个指向进行更新,现在指向了我们当前的节点了,然后我们的cur也进行了更新了,指向当前节点的下个节点了,下个节点我们一开始使用tmp进行保存了,然后我们直接进行赋值就行了
等循环结束了,我们的链表的遍历操作就结束了,那么就说明我们的链表已经逆置成功了,那么现在我们的prev就是我们的头结点了
然后我们从这个头结点进行遍历操作,我们遍历k次,所以我们的循环条件是--k,前置–,返回的是-之前的值
等循环结束了,我们的perv就是我们原先链表的倒数第k个节点了,我们直接将这个节点的值进行返回就行了


1.3 解法二代码以及解释

int kthToLast(struct ListNode* head, int k){struct ListNode* first = head;struct ListNode* last = head;for(int i = 1; i < k ;i++)first = first->next;while(first->next){first = first->next;last=last->next;}return last->val;
}

我们先创建了两个指针fastlast,然后都初始化指向头结点,但是我们让块指针先走k步,然后我们继续使用while循环进行遍历操作,但是是快慢指针一起进行遍历,然后循环的条件就是快指针走到了尾节点的时候我们直接将尾节点的值进行返回就行了
但是这个原理是为什么呢?

双指针法的原理可以通过以下几点进行解释:

  1. 快慢指针之间的距离固定为 k
    双指针法的核心思想是利用两个指针:一个“快指针”(fast)和一个“慢指针”(slow)。我们首先让 快指针先走 k,这样快指针和慢指针之间的距离就正好是 k

  2. 同时移动快指针和慢指针
    接下来,当我们同时移动快慢指针时,快指针每走一步,慢指针也走一步。因为快指针最开始已经领先 k 步,因此当快指针走到链表末尾时,慢指针的位置就是倒数第 k 个节点。

  • 具体来说,假设链表的长度为 n,当快指针走到末尾时,它已经走了 n 步。而由于快指针最开始比慢指针多走了 k 步,因此慢指针只走了 n - k 步,此时 slow 就恰好指向倒数第 k 个节点。
  1. 保持链表的一次遍历
    通过这种方式,我们只需要遍历链表一次,而不是两次就可以得到倒数第 k 个节点。相比于朴素方法(先遍历链表得到链表长度,再遍历到目标节点位置)要遍历两次链表的时间复杂度,双指针法将时间复杂度从 O(2n) 优化到了 O(n)

总结原理:

  • 步数差:快指针和慢指针在一开始保持 k 步的差距,这样当快指针到达末尾时,慢指针正好停在倒数第 k 个节点的位置。
  • 一次遍历:只需要遍历链表一次就能完成任务,避免了多次遍历的低效。
  • 指针同步移动:当快指针到达链表末尾时,慢指针正好位于我们想要的倒数第 k 个节点。

2.相交链表

在这里插入图片描述

题目传送门


2.1 题目说明

从图中提取的题目信息如下:

题目描述
给你两个单链表的头节点 headAheadB,请你找出并返回两个单链表相交的起始节点。如果两个链表不存在相交节点,则返回 null
在这里插入图片描述

注意:

  • 整个链表结构中不存在环。
  • 你不能更改链表的结构,链表必须保持其原始结构。

示例 1

在这里插入图片描述

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at '8'

示例 2

在这里插入图片描述

输入:intersectVal = 2, listA = [1,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1
输出:Intersected at '2'

示例 3

在这里插入图片描述

输入:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2
输出:null

输入参数:

  • intersectVal:相交的起始节点的值。如果不存在相交节点,则该值为 0。
  • listA:链表 A。
  • listB:链表 B。
  • skipA:在链表 A 中(从头节点开始)跳到交叉节点的节点数。
  • skipB:在链表 B 中(从头节点开始)跳到交叉节点的节点数。

输出:

  • 如果链表相交,返回相交的起始节点的值;如果不相交,返回 null

2.2 题目分析

这个题给我们两个链表,让我们找出两个链表的相交链表,然后将相交节点进行返回的操作,如果没有相交的节点的话我们直接返回NULL
那么这个题我们应该怎么进行设置呢?
可能给的两个链的长度不一样啊,那么我们应该怎么解决呢?
我们可以找出长链,然后计算出两个链的节点之差k,然后让长链走k次,那么我们的长链和短链就是同一个起点了,然后一起进行遍历的操作,边遍历边进行大小的比较的操作,如果两个链表遍历的指针相遇了的话,那么当前的指针所处的节点就是相交的节点了
那么思路就说到这里了,下面就是我们的代码的实践了


2.3 代码部分

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     struct ListNode *next;* };*///我们需要找到两个链表节点的差值//长链表先走差值数//两个链表开始遍历操作,看看是不是同一个节点typedef struct ListNode ListNode;
struct ListNode *getIntersectionNode(struct ListNode *headA, struct ListNode *headB)
{if(headA==NULL||headB==NULL){return NULL;}//创建两个指针分别指向A和B两个链表ListNode*l1=headA;ListNode*l2=headB;//计算两个链表的节点的个数int sizeA=0,sizeB=0;while(l1!=NULL)//先遍历l1{sizeA++;l1=l1->next;}while(l2!=NULL)//先遍历l1{sizeB++;l2=l2->next;}//求差值int gap=abs(sizeA-sizeB);//绝对值//我们需要判断下谁是长链表//我们先假设ListNode*longlist=headA;ListNode*shortlist=headB;if(sizeA<sizeB){longlist=headB;shortlist=headA;}//到这里我们就知道长短链表了while(gap--){longlist=longlist->next;}//上面的代码是找到长链表然后让长链表的指针走差值while(longlist&&shortlist)//两个链表不为空的话我们就往后面走{if(longlist==shortlist)//说明相交了{return longlist;}//如果没有相交的话,那么我们的两个指针接着走longlist=longlist->next;shortlist=shortlist->next;}//到这里的话据说明没有相交的节点,我们直接返回空就行了return NULL;}

2.4 代码分析

我们先将特殊情况进行分析下,如果两个链表都是空的话,我们直接返回NULL就行了
然后我们就开始处理正常情况了
我们先创建两个指针分别指向我们的AB两个链表,分别是l1l2,指向对应链表的头结点
我们然后创建两个变量进行记录两个链表的头结点到尾节点的节点个数
然后我们就可以算出差值gap了,然后我们进行长短链表的判断假设,我们先假设长链表是A,然后加链表是B,如果sizeA<sizeB的话,那么长链表就是B,短链表就是A
然后我们就可以将长短链表判断出来了
我们利用sizeA<sizeB算出了节点差值 gap,我们利用abs进行绝对值的操作
直到长链表是谁之后,我们让长链表走gap
走完之后我们的两个链表一起进行遍历,使用while循环,条件是两个链表不为空我们就往后走
然后在循环里面进行判断,如果长链表的指针等于短链表的指针,那么就说明两个指针相遇了,那么这个节点就是我们想要的相交节点了
在这个条件判断之后我们进行两个指针的往后走一位的操作
如果出了循环还没有返回的话,那么就说明这两个链表是不存在相交的节点的,我们直接返回NULL就行了

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

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

相关文章

15分钟学 Go 第 10 天:函数参数和返回值

第10天&#xff1a;函数参数和返回值 目标&#xff1a;理解函数如何传递参数 在Go语言中&#xff0c;函数是程序的基本构建块。了解如何传递参数和返回值是编写高效、可复用代码的重要步骤。本文将详细讲解函数参数的类型、传递方式以及如何处理返回值&#xff0c;辅以代码示…

用C++编写一个简单的游戏引擎:从游戏循环到物理与渲染的全面解析

解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 构建一个基础的2D游戏引擎是一项富有挑战性但极具学习价值的任务。本文将通过从零开始的方式,逐步讲解如何使用C++开发一个简单的游戏引擎。内容涵盖了游戏引擎的核心架构设计,包括游戏循环、物理引擎和图形渲染…

DP—子数组,子串系列 第一弹 -最大子数组和 -环形子数组的最大和 力扣

你好&#xff0c;欢迎阅读我的文章~ 个人主页&#xff1a;Mike 所属专栏&#xff1a;动态规划 ​ 53. 最大子数组和 最大子数组和 ​ 分析: 使用动态规划解决 状态表示: 1.以某个位置为结尾 2.以某个位置为起点 这里使用以某个位置为结尾&#xff0c;结合题目要求&#…

MySQL8.0主从同步报ERROR 13121错误解决方法

由于平台虚拟机宿主机迁移&#xff0c;导致一套MySQL主从库从节点故障&#xff0c;从节点服务终止&#xff0c;在服务启动后&#xff0c;恢复从节点同步服务&#xff0c;发现了如下报错&#xff1a; mysql> show slave status\G; *************************** 1. row *****…

GDAL+C#实现矢量多边形转栅格

1. 开发环境测试 参考C#配置GDAL环境&#xff0c;确保GDAL能使用&#xff0c;步骤简述如下&#xff1a; 创建.NET Framework 4.7.2的控制台应用 注意&#xff1a; 项目路径中不要有中文&#xff0c;否则可能报错&#xff1a;can not find proj.db 在NuGet中安装GDAL 3.9.1和G…

OSI参考模型详解:初学者指南与实践案例

OSI参考模型详解&#xff1a;初学者指南与实践案例 OSI&#xff08;Open System Interconnect&#xff09;参考模型是一个由国际标准化组织&#xff08;ISO&#xff09;提出的七层网络分层模型&#xff0c;它为全球所有互联计算机系统提供了一个通用的通信框架&#xff0c;解决…

【Mysql】-锁机制-GAP锁

在 MySQL 的 InnoDB 存储引擎中&#xff0c;Gap 锁&#xff08;间隙锁&#xff09;是一种用于防止幻读的锁机制。幻读是指在一个事务中&#xff0c;多次执行相同的查询&#xff0c;结果集却不同&#xff0c;通常是由于其他事务插入了新的行。为了防止这种情况&#xff0c;InnoD…

无人机之自主飞行关键技术篇

无人机自主飞行指的是无人机利用先进的算法和传感器&#xff0c;实现自我导航、路径规划、环境感知和自动避障等能力。这种飞行模式大大提升了无人机的智能化水平和操作的自动化程度。 一、传感器技术 传感器是无人机实现自主飞行和数据采集的关键组件&#xff0c;主要包括&a…

软考-软件设计师(10)-专业英语词汇汇总与新技术知识点

场景 以下为高频考点、知识点汇总。 软件设计师上午选择题知识点、高频考点、口诀记忆技巧、经典题型汇总: 软考-软件设计师(1)-计算机基础知识点:进制转换、数据编码、内存编址、串并联可靠性、海明校验码、吞吐率、多媒体等: 软考-软件设计师(1)-计算机基础知识点:进制…

C语言复习第3章 函数

目录 一、函数介绍1.1 函数是什么1.2 C语言中函数的分类1.3 函数原型1.4 高内聚 低耦合1.5 C语言main函数的位置 二、函数的参数2.1 实参和形参2.2 函数的参数(实参)可以是表达式2.3 传值与传址(swap函数)2.4 明确形参是实参的临时拷贝2.5 void(如果不写函数返回值 默认是int)2…

python 爬虫 入门 三、登录以及代理。

目录 一、登录 &#xff08;一&#xff09;、登录4399 1.直接使用Cookie 2.使用账号密码进行登录 可选观看内容&#xff0c;使用python对密码进行加密&#xff08;无结果代码&#xff0c;只有过程分析&#xff09; 二、代理 免费代理 后续&#xff1a;协程&#xff0c;…

如何在OceanBase中新增系统变量及应用实践

因为系统变量涉及复杂的工程文件&#xff0c;为防止新增变量操作对软件系统的潜在影响&#xff0c;OceanBase为多数开发者设计了一套高效的编程框架。此框架允许开发者在新增及使用系统变量时&#xff0c;仅需专注于变量定义的细节。具体来说&#xff0c;通过运行一个Python脚本…

树莓派设置中文界面

树莓派设置中文界面 1.安装中文字体。 执行命令&#xff1a;sudo apt-get -y install ttf-wqy-zenhei 2.设置显示中文。 执行命令&#xff1a;sudo raspi-config 选择&#xff1a;4 Localisation Options --> 1 Change Locale 按空格键在前面打勾或去掉勾&#xff0…

Windows 11开发环境搭建与应用开发实践

1. 引言 随着微软发布Windows 11,操作系统领域迎来了许多新的功能和变化。Windows 11不仅优化了用户界面,还强化了性能与安全性,增加了对开发者友好的特性,使其成为一个理想的开发平台。无论是桌面应用、Web应用,还是跨平台移动应用,Windows 11都为开发者提供了强大的支…

企业级调度器 LVS

集群和分布式基础知识 系统性能的扩展方式 当一个系统&#xff0c;或一个服务的请求量达到一定的数量级的时候&#xff0c;运行该服务的服务器的性能和资源上限&#xff0c; 很容易成为其性能瓶颈。除了性能问题之外&#xff0c;如果只部署在单台服务器上&#xff0c;在此服务…

gitee建立/取消关联仓库

目录 一、常用指令总结 二、建立关联具体操作 三、取消关联具体操作 一、常用指令总结 首先要选中要关联的文件&#xff0c;右击&#xff0c;选择Git Bash Here。 git remote -v //查看自己的文件有几个关联的仓库git init //初始化文件夹为git可远程建立链接的文件夹…

uniapp uni.uploadFile errMsg: “uploadFile:fail

uniapp 上传后一直显示加载中 1.检查前后端上传有无问题 2.检查失败信息 await uni.uploadFile({url,filePath,name,formData,header,timeout: 30000000, // 自定义上传超时时间fail: async function(err) {$util.hideAll()// 失败// err 返回 {errMsg: "uploadFile:fai…

速盾:cdn能加速游戏吗?

CDN&#xff08;内容分发网络&#xff09;是一种通过分布在全球不同地区的服务器来缓存和传输网络内容的技术。它的主要目的是提高内容的传输速度和用户体验。虽然CDN主要用于加速网站的访问和内容传输&#xff0c;但它也可以应用于游戏加速。 在传统的在线游戏中&#xff0c;…

SpringCloud学习:Openfeign组件实现服务调用和负载均衡

OpenFeign&#xff1a;服务调用与负载均衡&#xff08;服务端接口&#xff09; 是什么&#xff1a;通过OpenFeign可以实现服务调用和负载均衡 OpenFeign是一个声明性web服务客户端&#xff0c; 怎么用&#xff1a;服务提供者提取公共接口用FrignClient标注&#xff0c;服务调…

【Flutter】基础入门:开发环境搭建

Flutter 是一个强大的跨平台框架&#xff0c;支持在 Android、iOS、Windows、Linux、Web 等多种平台上开发应用。下面将详细介绍如何在各个平台上构建 Flutter 开发环境&#xff0c;并使用相同的项目代码构建出一个可以在多个平台运行的跨平台 Demo。 Flutter 环境配置&#x…