【算法day4】链表:应用拓展与快慢指针

题目引用


  1. 两两交换链表节点
  2. 删除链表的倒数第n个节点
  3. 链表相交
  4. 环形链表

1.两两交换链表节点


给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。
示例 1:
在这里插入图片描述
输入:head = [1,2,3,4]
输出:[2,1,4,3]
示例 2:
输入:head = []
输出:[]
示例 3:
输入:head = [1]
输出:[1]

我们先来看一下题目,这题跟昨天的翻转链表比较相似,都是控制节点指针对链表进行修改,这里呢我们先new一个虚拟头结点dummyhead来保证到最后可以找到头结点返回,然后定义一个指针curdummyhead位置,tmpcur->next位置来对其进行修改,tmp1用于标记后面节点避免剩余链表丢失。初始化定义
接着将curnext指向tmp的下一个节点
在这里插入图片描述
再将这个节点的next指向tmp节点
在这里插入图片描述
最后将tmp位置节点next指向tmp1,而cur顺势移动到tmp位置进行下一轮交换。
在这里插入图片描述
最后将dummyhead删除,本题就做完啦~
代码:

ListNode* swapPairs(ListNode* head) {ListNode* dummyhead=new ListNode(-1);dummyhead->next=head;ListNode* cur=dummyhead;while(cur->next!=nullptr&&cur->next->next!=nullptr){ListNode* tmp=cur->next;ListNode* tmp1=cur->next->next->next;cur->next=cur->next->next;cur->next->next=tmp;tmp->next=tmp1;cur=tmp;}ListNode* result=dummyhead->next;delete dummyhead;return result;}

2.删除链表的倒数第n个节点

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。
示例 1:
在这里插入图片描述
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]
示例 2:
输入:head = [1], n = 1
输出:[]
示例 3:
输入:head = [1,2], n = 1
输出:[1]

首先我们分析一下题目,这道题目是可以通过遍历两遍的方式做出来的,先遍历一遍算出链表长度,再算出差值,删除节点。但是这里亦可以用快慢指针来做,并且只需要一次遍历。
首先new一个虚拟头结点dummyhead,再定义fastslow指针都指向dummyhead。再我们让fast先移动n+1个节点,再fastslow节点同时移动,直到fast为空。然后删除slow后面的节点返回链表。
为什么是n+1个节点,为什么同时移动呢?
首先回答为什么先让fast先走再同时移动,因为当fastslow同时移动时,fastslow保持了相对距离n+1,当fast移动到链表结束位置时,slow与其刚好相差n+1个节点,也就实现了一次遍历找到倒数第n个节点的期望。
那么为什么是n+1呢?因为当我们找到刚好是倒数第n个位置的节点时,我们对其进行移除操作是很困难的,所以找到倒数第n+1个刚刚好可以将第n个轻易的删除掉。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
附上代码:

ListNode* removeNthFromEnd(ListNode* head, int n) {if(head->next==nullptr) return nullptr;ListNode* dummyhead=new ListNode(0);dummyhead->next=head;ListNode* fast=dummyhead;ListNode* slow=dummyhead;while(n>=0){fast=fast->next;n--;}while(fast!=nullptr){fast=fast->next;slow=slow->next;}ListNode* tmp=slow->next;slow->next=slow->next->next;delete tmp;return dummyhead->next;}

3.链表相交

给你两个单链表的头节点 headA 和 headB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null 。
图示两个链表在节点 c1 开始相交:
题目数据 保证 整个链式结构中不存在环。
注意,函数返回结果后,链表必须 保持其原始结构 。
示例 1:
在这里插入图片描述

输入:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, skipB = 3
输出:Intersected at ‘8’
解释:相交节点的值为 8 (注意,如果两个链表相交则不能为 0)。
从各自的表头开始算起,链表 A 为 [4,1,8,4,5],链表 B 为 [5,0,1,8,4,5]。
在 A 中,相交节点前有 2 个节点;在 B 中,相交节点前有 3 个节点。

这道题很简单,我们先通过两次遍历得到两个链表的长度,然后算出长度差,让长的链表的指针先走长度差gap步,接着两个指针同时移动一一比对,相等即返回。

ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {int lenA=0,lenB=0;ListNode* curA=headA;ListNode* curB=headB;while(curA){curA=curA->next;lenA++;}while(curB){curB=curB->next;lenB++;}curA=headA;curB=headB;if (lenB > lenA) {swap (lenA, lenB);swap (curA, curB);}// 求长度差int gap = lenA - lenB;// 让curA和curB在同一起点上(末尾位置对齐)while (gap--) {curA = curA->next;}while(curA){if(curA==curB){return curA;}curA=curA->next;curB=curB->next;}return NULL;}

4.环形链表II

给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
不允许修改 链表。
示例 1:
在这里插入图片描述
输入:head = [3,2,0,-4], pos = 1
输出:返回索引为 1 的链表节点
解释:链表中有一个环,其尾部连接到第二个节点。

首先,我们需要判断一下是否是环形链表,定义一个fast和一个slowfast每次走两步,slow每次走一步,如果有环,那么fastslow一定会在环内的某个位置碰上,因为fastslow有速度差。
那么怎么找到环形链表的开头呢?
这就牵扯到数学问题,设头到环的入口的长度为x,入口到fastslow相遇的位置的长度为y,环剩下的长度为z,那么不难得出

2*(x+y)=n*(y+z)+x+y
x+y=n*(y+z)
x=n*(y+z)-y
x=(n-1)(y+z)+z
那么就说明了从头结点出发一个指针,fast出发一个指针,他们相遇的位置就是环形链表的入口。

那么代码如下:

ListNode *detectCycle(ListNode *head) {ListNode* fast=head;ListNode* slow=head;while(fast&&fast->next){fast=fast->next->next;slow=slow->next;if(slow==fast){ListNode* i1=head;ListNode* i2=fast;while(i1!=i2){i1=i1->next;i2=i2->next;}return i1;}}return NULL;}

总结

今天的题目都比较考验画图和发现规律的能力,沉下心好好学习,慢慢寻找总能找到规律。

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

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

相关文章

【Gitlab】gitrunner并发配置

并发介绍 涉及到并发控制的一共有4个参数: concurrent , limit ,request_concurrency,parallel 全局的配置: [rootiZ2vc6igbukkxw6rbl64ljZ config]# vi config.toml concurrent 4 #这是一个总的全局控制,它限制了所有pipline,所有runner执行器…

【Vue3】【Naive UI】<NDropdown>标签

【Vue3】【Naive UI】 标签 基本设置自定义渲染交互事件其他属性 【VUE3】【Naive UI】<NCard> 标签 【VUE3】【Naive UI】<n-button> 标签 【VUE3】【Naive UI】<a> 标签 【VUE3】【Naive UI】&#xff1c…

vue 2 父组件根据注册事件,控制相关按钮显隐

目标效果 我不注册事件,那么就不显示相关的按钮 注册了事件,才会显示相关内容 实现思路 组件在 mounted 的时候可以拿到父组件注册监听的方法 拿到这个就可以做事情了 mounted() {console.log(this.$listeners, this.$listeners);this.show.search !…

四:工具、环境准备-compute node

一:工具、环境准备-controller node 二:OpenStack环境准备-controller node 三:安装服务-controller node 四:工具、环境准备-compute node 五:OpenStack环境准备-compute node 六:安装服务-compute node 七…

Vue3在PC端接入萤石云监控

参考文档&#xff1a;文档概述 萤石开放平台API文档 1.安装依赖 npm i ezuikit-js 2.封装组件 src/components/PlayerVideo/index.vue <template><div id"video-container" style"width: 100%;"></div> </template> <scrip…

快排详解(4种写法:霍尔/挖坑法/双指针/非递归)

//本文所写快排的结果都是从小到大排序 思路 快排就是把数组的第一个值记为key,然后定义两个指针,一个叫begin,一个叫end. begin指针从数组的头部出发,寻找比key大的值;end指针从数组的尾部出发,寻找比key小的值; 然后交换begin和end的值 ......最后,begin和end相遇就停下…

ESP32驱动PCM5102A播放SD卡音频

文章目录 简介模块参数功能框图引脚定义通信接口和通信数据格式通信流程引脚接线ESP32和PCM5102AESP32和SD模块 主要代码spi.hSD.hAudio.h实验效果总结 简介 PCM5102A模块是一款立体声DAC模块、音频数模转换器&#xff0c;内部集成了PCM5102芯片。PCM5102芯片是集成了立体声模…

ProtonBase 教育行业解决方案

01/方案概述 当前&#xff0c;大数据、云计算等技术正加速教育行业的数字化转型&#xff0c;教学模式从线下转向线上&#xff0c;传统教育企业向具有互联网性质的新型教育企业转变。在此背景下&#xff0c;教育企业亟需探索多源数据的融合扩展&#xff0c;以应对复杂的业务场景…

spark读取hbase数据

使用Apache Spark读取HBase数据是一个常见的操作&#xff0c;通常用于大数据处理和分析。Apache Spark 提供了与 HBase 集成的工具&#xff0c;可以通过 Spark-HBase 连接器来实现这一功能。以下是一个详细的步骤指南和示例代码&#xff0c;帮助你使用 Spark 读取 HBase 中的数…

2025年人工智能,自动化与机械工程国际学术会议(AIAME2025)

早鸟通道开启&#xff1a; 2025年人工智能&#xff0c;自动化与机械工程国际学术会议&#xff08;AIAME2025&#xff09; 2025 International Conference on Artificial Intelligence, Automation, and Mechanical Engineering 【重要日期】 早鸟征稿截止日期&#xff1a;…

在SpringBoot当中设置MySQL兼容unicode编码

类似报错 java.sql.SQLException: Unsupported character encoding utf8mb4at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:129) ~[mysql-connector-j-8.0.31.jar:8.0.31]at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.…

网络技术-不使用K8S情况下哪些方法可搭建服务链编排

在不使用Kubernetes&#xff08;k8s&#xff09;&#xff08;或不使用Docker环境技术的&#xff09;情况下&#xff0c;搭建服务链编排环境需要依赖其他服务编排和容器化技术&#xff0c;或者采用传统的虚拟机和服务管理方法。以下是一些可能的解决方案&#xff1a; 一、使用其…

[C++并发编程] 线程基础

线程发起 最简单的发起一个线程。 void thread_work(std::string str) {std::cout << "str: " << std << std::endl; } //初始化并启动一个线程 std::thread t1(thread, wangzn2016); 线程等待&#xff1a; 线程发起后&#xff0c;可能新的线…

C++ STL 容器系列(三)list —— 编程世界的万能胶,数据结构中的百变精灵

STL系列学习参考&#xff1a; C STL系列__zwy的博客-CSDN博客https://blog.csdn.net/bite_zwy/category_12838593.html 学习C STL的三个境界&#xff0c;会用&#xff0c;明理&#xff0c;能扩展&#xff0c;STL中的所有容器都遵循这个规律&#xff0c;下面我们就按照这三个境…

UE5 打包环境、C++环境安装说明

文章目录 前言一、安装 Visual Studio 及其必装组件1. 下载安装包1.1 方法11.1 方法22. 安装 Visual Studio3. 修改安装位置(可选)4. 勾选必装组件二、打包错误排查1. 错误:Visual Studio 2022 compiler version 14.42.34433 is not a preferred version. Please use the la…

【AI技术赋能有限元分析应用实践】Abaqus有限元分析到深度学习方法应用全过程——汽车刹车片热力耦合分析

目录 一、项目实现介绍**项目背景****项目目标****项目流程概述****技术融合****项目价值** 二、实现流程**Step 1: 分析问题构建方法&#xff0c;寻找主要分析目标&#xff0c;确定初步目标****Step 2: 使用 Abaqus 完成有限元仿真&#xff0c;后处理并保存数据为 odb 格式***…

从0开始linux(38)——线程(1)线程概念

欢迎来到博主专栏&#xff1a;从0开始linux 博主ID&#xff1a;代码小豪 文章目录 进程与线程线程概念线程的优点线程的独立数据 进程与线程 如果要理解线程&#xff0c;那么进程将会时绕不开的点。首先我们回顾一下我们之前在进程章节当中是如何描述进程的&#xff1f; 进程&…

Vue中的计算属性和监听属性

在Vue中&#xff0c;计算属性和监听属性是两种非常有用的功能&#xff0c;它们可以帮助我们更好地管理数据和响应数据的变化。 计算属性 计算属性是基于它们的依赖进行缓存的。只有当依赖发生变化时&#xff0c;计算属性才会重新计算。这使得计算属性非常适合用于执行昂贵的计…

Doge东哥wordpress主题

Doge东哥wordpress主题是一款专为中小型企业设计的WordPress外贸网站模板&#xff0c;它以其现代、专业且用户友好的界面&#xff0c;为企业提供了一个展示产品和服务的理想平台。以下是对该模板的详细描述&#xff1a; 首页设计概览 首页的设计简洁而不失大气&#xff0c;顶…

keil 5. Flash Timeout. Reset the Target and try it again.

使用官方STM32 ST-LINK Utility 烧写软件 KEIL 5, 设置DFP 包支持FLASH烧写算法 Keil 5, Flash Timeout. Reset the Target and try it again.-CSDN博客