代码随想录算法训练营第4天 | 24. 两两交换链表中的节点 , 19.删除链表的倒数第N个节点 , 面试题 02.07. 链表相交 , 142.环形链表II

链表知识基础

文章链接:https://programmercarl.com/%E9%93%BE%E8%A1%A8%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html#

24. 两两交换链表中的节点

题目链接:https://leetcode.cn/problems/swap-nodes-in-pairs/
使用虚拟头结点,这样会方便很多,要不然每次针对头结点(没有前一个指针指向头结点),还要单独处理。

思路:使用虚拟头结点

设置一个虚拟头结点,这样原链表的所有节点就都可以按照统一的方式进行移除了。
然后注意一下,就是while里面,判断的条件有两个,pre.next != null && pre.next.next != null,才可以交换,也就是后面一个,和后面两个结点都不是null的情况,才可以。同时写的顺序也不能反,否则会报null.next的错误

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode swapPairs(ListNode head) {ListNode dummyNode = new ListNode(-1);dummyNode.next = head;ListNode pre = dummyNode;while(pre.next != null && pre.next.next != null){// ListNode tmp = pre.next.next;// pre.next.next = tmp.next;// tmp.next = pre.next;// pre.next = tmp;// pre = pre.next.next;ListNode firstNode = pre.next;ListNode secondNode = pre.next.next;firstNode.next = secondNode.next;secondNode.next = pre.next;pre.next = secondNode;pre = pre.next.next;}return dummyNode.next;}
}

时间复杂度 O(n)

19. 删除链表的倒数第 N 个结点

题目连接:https://leetcode.cn/problems/remove-nth-node-from-end-of-list/description/

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。尝试用一遍扫描实现。

解法:快慢指针

让快指针先移动n步,然后这样再同时移动。
此时快指针移动了size-n步,慢指针也是size-n步,此时慢指针离最后距离也是size-(size-n)=n,也就是题意。
写过一次,有思路就很快了。

/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode() {}*     ListNode(int val) { this.val = val; }*     ListNode(int val, ListNode next) { this.val = val; this.next = next; }* }*/
class Solution {public ListNode removeNthFromEnd(ListNode head, int n) {ListNode dummyNode = new ListNode(-1);dummyNode.next = head;// 快慢双指针ListNode slow=dummyNode,fast=dummyNode;// 快指针先移动n步for(int i=0;i<n;i++){fast = fast.next;}// 然后这个时候,快指针和慢指针,再同时移动。直到快指针移动到最后while(fast.next!=null){fast = fast.next;slow = slow.next;}// 此时的slow指针指向的是要删除的结点的前一个slow.next = slow.next.next;return dummyNode.next;}
}

时间复杂度O(n)

面试题 02.07. 链表相交

题目连接:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/

解法:求两个链表交点节点的指针

特别注意!!! 交点不是数值相等,而是指针相等。不用比较val,只要比较两个指针是否相等,即可
还有个地方,两个链表的末端一定要先对齐,要不然不满足题意。也就是说,两个链表的指针起始位置是不一样的。一个是在开始处,一个不是。
在这里插入图片描述

/**
/*** Definition for singly-linked list.* public class ListNode {*     int val;*     ListNode next;*     ListNode(int x) {*         val = x;*         next = null;*     }* }*/
public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {// 先求两个链表的长度int lenA = 0, lenB = 0;ListNode curA = headA,curB = headB;while(curA!= null){curA = curA.next;++lenA;}while(curB!=null){curB = curB.next;++lenB;}curA = headA;curB = headB;// 把A确定为更长的if(lenA<lenB){// 交换结点ListNode tmp = curB;curB = curA;curA = tmp;int tmpLen = lenB;lenB = lenA;lenA = tmpLen;}// 对齐末端int gap = lenA-lenB;while(gap-- >0){curA = curA.next;}// 然后这个时候再比较指针是否相同,不是比较val是否相同while(lenB-- >0){if(curA==curB){return curA;}curA = curA.next;curB = curB.next;}return null;}
}

时间复杂度:O(n)

142.环形链表II

题目连接:https://leetcode.cn/problems/linked-list-cycle-ii/

解法1:快慢指针法

主要考察两知识点:
(1)判断链表是否环
(2)如果有环,如何找到这个环的入口

判断链表是否有环

可以使用快慢指针法,分别定义 fast 和 slow 指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。相对于slow来说,fast是一个节点一个节点的靠近slow的,所以fast一定可以和slow重合。

如果有环,如何找到这个环的入口

假设从头结点到环形入口节点 的节点数为x。 环形入口节点到 fast指针与slow指针相遇节点 节点数为y。 从相遇节点 再到环形入口节点节点数为 z。 如图所示:
在这里插入图片描述
slow指针走过的节点数为: x + y, fast指针走过的节点数:x + y + n (y + z),n为fast指针在环内走了n圈才遇到slow指针, (y+z)为 一圈内节点的个数A。
(slow指针肯定是走了一圈不到的,因为他俩的速度差在一圈内是完全追的上的)

因为fast指针是一步走两个节点,slow指针一步走一个节点, 所以 fast指针走过的节点数 = slow指针走过的节点数 * 2:

(x + y) * 2 = x + y + n (y + z)

两边消掉一个(x+y): x + y = n (y + z)

因为要找环形的入口,那么要求的是x,因为x表示 头结点到 环形入口节点的的距离。

所以要求x ,将x单独放在左面:x = n (y + z) - y ,

再从n(y+z)中提出一个 (y+z)来,整理公式之后为如下公式:x = (n - 1) (y + z) + z 注意这里n一定是大于等于1的,因为 fast指针至少要多走一圈才能相遇slow指针。

这个公式说明什么呢?

先拿n为1的情况来举例,意味着fast指针在环形里转了一圈之后,就遇到了 slow指针了。

当 n为1的时候,公式就化解为 x = z,

这就意味着,从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是 环形入口的节点。

也就是在相遇节点处,定义一个指针index1,在头结点处定一个指针index2。

让index1和index2同时移动,每次移动一个节点, 那么他们相遇的地方就是 环形入口的节点。

/*** Definition for singly-linked list.* class ListNode {*     int val;*     ListNode next;*     ListNode(int x) {*         val = x;*         next = null;*     }* }*/
public class Solution {public ListNode detectCycle(ListNode head) {// 方法2:快慢指针ListNode slowIndex = head,fastIndex = head;while(fastIndex!=null && fastIndex.next != null){// 快指针一次移动两格,慢指针一次移动一格fastIndex = fastIndex.next.next;slowIndex = slowIndex.next;// 有环的情况if(slowIndex == fastIndex){// 相交的点ListNode joint = slowIndex;ListNode startNode = head;// 需要数学证明!// 从头结点出发一个指针,从相遇节点也出发一个指针,这两个指针每次只走一个节点, // 那么当这两个指针相遇的时候就是 环形入口的节点。while(startNode!=joint){joint = joint.next;startNode = startNode.next;}return joint;}}return null;}
}

时间复杂度:O(n)
空间复杂度:O(1)

解法2:哈希法

一种非常直观的解法,我们遍历链表中的每个节点,并将它记录下来;一旦遇到了此前遍历过的节点,就可以判定链表中存在环。借助哈希表可以很方便地实现。

/*** Definition for singly-linked list.* class ListNode {*     int val;*     ListNode next;*     ListNode(int x) {*         val = x;*         next = null;*     }* }*/
public class Solution {public ListNode detectCycle(ListNode head) {// 方法1:哈希表的方式ListNode cur = head;HashSet<ListNode>nodes = new HashSet<ListNode>();while(cur!=null){if(nodes.contains(cur))return cur;elsenodes.add(cur);cur = cur.next;}return null;}
}

时间复杂度:O(n)
空间复杂度:O(n),n为链表中节点的数目

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

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

相关文章

Promise和箭头函数和普通函数的区别

\1. Promise 的理解 Promise 是一种为了避免回调地狱的异步解决方案 2. Promise 是一种状态机&#xff1a; pending&#xff08;进行中&#xff09;、fulfilled&#xff08;已成功&#xff09;和rejected&#xff08;已失败&#xff09; 只有异步操作的结果&#xff0c;可以决…

Centos7编译Python3.11源码并安装完成的详细教程

Python3.11的Linux源码&#xff1a; Index of /ftp/python/https://www.python.org/ftp/python/由于Centos7里自带的openssl是1.0版本的&#xff0c;而Centos Stream8和9用的是openssl-1.1.1版本的。 注意&#xff1a;openssl必须是openssl-1.1.1版本的&#xff0c;虽然最高版…

QT的事件机制

QT的事件机制 文章目录 QT的事件机制 1、QT的事件机制。2、QT事件的整体流程。1、事件处理函数。1、鼠标按下与鼠标释放事件。2、事件的接收与忽略(accept()和ignore()函数&#xff09;。 2.事件的分发enevt()1、事件分发的dome。2、enevt事件的缺点。 3、事件的过滤器。 3、总…

通过本质看现象:关于Integer受内部初始化赋值范围限制而出现的有趣现象

文/朱季谦 这是我很多年前的第一篇技术博客&#xff0c;当时作为一名技术小菜鸟&#xff0c;总体而言显得很拙见&#xff0c;但也算是成长路上的一个小脚印&#xff0c;希望能在以后的日子里&#xff0c;可以对JAVA技术有一个更加深入的思考与认识。 前几天我在逛论坛的时候&a…

SSM基础入门

SSM Mybatis、Spring和SpringMVC这三个框架整合在一起完成业务功能开发 文章目录 SSM5.1 流程5.2 详细步骤5.2.1 基本配置5.2.2 功能模块开发5.2.3 测试5.2.3.1 单元测试5.2.3.2 PostMan测试 5.3 统一结果封装5.3.1 概念5.3.2 实现 5.4 统一异常处理5.4.1 异常处理器的使用5.4…

自学习算法

自学习算法是一种基于深度学习的技术&#xff0c;通过大量的数据和模型训练&#xff0c;不断优化和改进模型的表现。 具体来说&#xff0c;自学习算法包括以下几个方面&#xff1a; 1.数据预处理&#xff1a;在训练模型之前&#xff0c;需要对大量的数据进行清洗、去重、标注…

Linux Centos7静默安装(非图形安装)Oracle RAC 11gR2(Oracle RAC 11.2.0.4)

Oracle RAC (全称Oracle Real Application Clusters &#xff09;静默安装&#xff08;非图形安装&#xff09;教程。 由于这篇文章花费了我太多时间&#xff0c;设置了仅粉丝可见&#xff0c;见谅。 环境说明&#xff1a; 虚拟机软件&#xff1a;VMware Workstation 16 Pro…

Git与VScode联合使用详解

目录 Git与VScode联合使用 方式一 1. 用vscode打开文件夹&#xff0c;如图点击初始化仓库&#xff0c;把此仓库初始为git仓库。 2. 提交文件到本地仓库 3. vscode与github账号绑定 4. 在github中建立远程仓库 5. 本地仓库与远程仓库绑定 方式二 1. 在github上建立远程仓…

VSCode添加Python解释器并安装Python库

目录 一、安装VSCode 二、安装Python解释器 1、安装包链接 2、安装过程 3、测试 4、安装flake8和yapf两个包 &#xff08;1&#xff09;安装flake8包 &#xff08;2&#xff09;安装yapf包 三、VSCode中选择python解释器 一、安装VSCode VSCode安装教程&#xff08;默…

Windows之任意文件删除到提权

前言 ZDI 发表过从任意文件夹删除到提权的利用过程&#xff0c;还提供了任意文件删除到提权的利用过程&#xff0c;所以一字之差但是漏洞利用方式也是有细微偏差的。 这里把任意文件删除和任意文件夹删除漏洞提权结合起来分析&#xff0c;是因为其最后的利用过程是一样的&…

Linux内核 - 同步机制之完成事件

背景 在复杂的软件系统中&#xff0c;常常存在多个并行运行的异步逻辑&#xff0c;然而&#xff0c;有些情况下&#xff0c;我们需要确保某些逻辑按照特定的时序顺序执行&#xff0c;以满足严格的时序要求。在这种情况下&#xff0c;我们可以使用同步机制&#xff0c;具体来说…

认识监控系统zabbix

利用一个优秀的监控软件&#xff0c;我们可以: ●通过一个友好的界面进行浏览整个网站所有的服务器状态 ●可以在 Web 前端方便的查看监控数据 ●可以回溯寻找事故发生时系统的问题和报警情况 了解zabbix zabbix是什么&#xff1f; ●zabbix 是一个基于 Web 界面的提供分布…

JVM:从零到入门

JVM&#xff0c;就是Java虚拟机。 JVM是一个巨大的话题&#xff0c;我们本文主要简单介绍一些围绕JVM相关的基础知识。 目录 JVM内存区域划分 本地方法栈 虚拟机栈 堆 程序计数器 方法区/ 元数据区 类加载 1.加载 2.验证 3.准备 4.解析 5.初始化 双亲委派模型 …

yydict属性字典-一种更加方便的方式访问字典

yydict属性字典-一种更加方便的方式访问字典 问题引入 这篇文章是想介绍 最近在使用字典的一种困惑. 我希望通过少写几个字符来访问 python中字典这种数据结构. 比如这个例子: person {name: frank,age: 18,hobby: swimming }在python中字典的定义 如上面的例子, 如果我希…

描述 power iteration(幂法)是啥?

幂法&#xff08;Power Iteration&#xff09;是一种迭代算法&#xff0c;用于计算一个矩阵的最大特征值和对应的特征向量。它是特征值求解问题中常用的一种方法。 幂法基于以下观察&#xff1a;如果一个矩阵 A 的某个特征向量 x 对应的特征值 λ 是最大的&#xff0c;那么当将…

spring boot mybatis plus mapper如何自动注册到spring bean容器

##Import(AutoConfiguredMapperScannerRegistrar.class) ##注册MapperScannerConfigurer ##MapperScannerConfigurer.postProcessBeanDefinitionRegistry方法扫描注册mapper ##找到mapper候选者 ##过滤mapper 类 候选者 ##BeanDefinitionHolder注册到spring 容器

vue项目之.env文件.env.dev、test、pro

.env文件是vue运行项目时的环境配置文件。 .env: 全局默认配置文件&#xff0c;所有环境(开发、测试、生产等&#xff09;均会加载并合并该文件 .env.development(开发环境默认命名) 开发环境的配置&#xff0c;文件名默认为.env.development,如果需要改名也是可以的&#xf…

安卓主板_MTK联发科低功耗迷你安卓核心板开发板定制开发

卓越V100安卓主板 是新移科技推出的4G物联网行业通用主板。卓越V100安卓主板基于 联发科MT6761安卓核心板设计&#xff0c;支持运行Android9.0 系统&#xff0c;通用性强&#xff0c;有很好的人机交互性&#xff0c;可进行二次开发&#xff0c;有良好的移植性。 另外&#xff…

面试经典150题(82-83)

leetcode 150道题 计划花两个月时候刷完&#xff0c;今天&#xff08;第四十一天&#xff09;完成了2道(82-83)150&#xff1a; 82.&#xff08;133. 克隆图&#xff09;题目描述&#xff1a; 给你无向 连通 图中一个节点的引用&#xff0c;请你返回该图的 深拷贝&#xff08…

ZZULIOJ 1118: 数列有序

题目描述 一个非递减有序的整型数组有n个元素&#xff0c;给定一个整数num&#xff0c;将num插入该序列的适当位置&#xff0c;使序列仍保持非递减有序。 要求定义一个函数insert()&#xff0c;将整数num插入在数组a的适当位置上&#xff0c;函数原型如下&#xff1a; void …