代码随想录二刷博客Day3~Day4

707. 设计链表

这道题的解题思路其实就是让我们模拟一个链表的实现:

首先我们先要创建一个内部类作为链表的结点,这个内部类要包含两个元素,一个是val值,一个是指向下一个节点的指针

在构造方法这里我们要初始化一个虚拟头街点和一个链表长度,使用虚拟头节点的好处在于可以统一处理各个节点,不用再单独处理头节点

然后在get方法这里,我们要使用一个cur指针从虚拟头节点开始出发,不断向后遍历直到我们需找到目标的节点,要注意的是,我们的下标值是要比我们cur要走过的步数少一位的,所以我们需要在step这个变量这里加上一位来确保我们能够走到目标的位置上

在处理头插法和尾插法这两个方法时候我们可以直接调用addAtIndex这个方法统一处理

在处理addAtIndex这个方法的时候,我们需要注意的是,我们要找到目标节点的前一个节点进行插入操作,所以根据刚才提到的我们的下标值是要比我们cur要走过的步数少一位的,我们直接让cur走index步,就可以到达目标节点的前一个节点!

同理处理deleteAtIndex这个方法的时候,我们的处理流程适合addAtIndex这个方法一样

具体代码如下

class MyLinkedList {class Node{int val;Node next;Node(int val){this.val = val;}}Node Dhead;int size;public MyLinkedList() {Dhead = new Node(-1);size = 0;}public int get(int index) {if(index < 0 || index >= size){return -1;}Node cur = Dhead;int step = index + 1;while(step-- > 0){cur = cur.next;}return cur.val;}public void addAtHead(int val) {addAtIndex(0,val);}public void addAtTail(int val) {addAtIndex(size,val);}public void addAtIndex(int index, int val) {if(index < 0 || index > size){return;}Node node = new Node(val);Node cur = Dhead;int step = index;while(step-- > 0){cur = cur.next;}node.next = cur.next;cur.next = node;++size;}public void deleteAtIndex(int index) {if(index < 0 || index >= size){return;}Node cur = Dhead;int step = index;while(step-- > 0){cur = cur.next;}cur.next = cur.next.next;size--;}
}

206. 反转链表

这道题的思路其实就是从前往后一步一步的修改指向,以给的示例为例子

我们定义两个指针一个pred指向虚拟头节点,一个cur指向pred指向节点的后一个节点

然后使用while循环不断地两个指针向后移动,在移动的过程中cur修改指向让cur.next = pred

在修改完毕后,由于我们的cur的后一个节点已经是pred了,所以我们在一开始就使用curNext来记录cur的后一个节点,在修改完毕后,让后pred走到cur的位置,cur走到curNext的位置上,这样就真正的让两个节点向后移动了

需要注意的时候在最后我们要将head(实际的头节点)的指向修改成空!因为虚拟头节点是我们自己定义的并不属于官方给的例子中

 最后贴上代码

class Solution {public ListNode reverseList(ListNode head) {if(head == null){return null;}ListNode Dhead = new ListNode();Dhead.next = head;ListNode pred = Dhead;ListNode cur = head;while(cur != null){ListNode curNext = cur.next;cur.next = pred;pred = cur;cur = curNext;}head.next = null;return pred;}
}

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

本题的关键就在于本题的题目“如何两两交换链表中的节点”,所以我们的思路就在于交换链表中的相邻的两个节点应该怎么样的交换

我们通过画图的形式来展现我们解题的思路

设置两个指针来记录我们要交换的节点,在我们两两交换完毕以后,需要对后面的链表进行操作,所以我们也需要一个指针来记录后面链表的头节点的位置,以方便我们进行修改指向

我们首先将头节点指向第二个节点,然后将第二个节点的指向修改成指向第一个节点,这样我们的交换就完成了,为了操作后面的链表,我们需要将第一个节点的指向修改成指向后面链表头节点的位置

    public ListNode swapPairs(ListNode head) {ListNode Dhead = new ListNode();Dhead.next = head;ListNode cur = Dhead;while(cur.next != null && cur.next.next != null){ListNode first = cur.next;ListNode second = cur.next.next;   ListNode third = cur.next.next.next;cur.next = second;second.next = first;first.next = third;cur = first;}return Dhead.next;}

这里需要注意的是while里面的终止条件,由于我们不知道链表的长度是奇数还是偶数,这个就需要注意cur是否会操作空指针,由于我们要交换的链表节点有两个,所以我们要保证两个节点都不为空,所以这里的终止条件就是

cur.next != null && cur.next.next != null 

还有一点我们要注意的是,在交换完以后,我们要让cur走到两两交换节点第一个节点的前一个节点上,所以我们要让 cur = first !

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

思路:怎么样才能删除倒数第N个节点呢?我一开始的思路是让cur指针指向头节点后一直向后走,走到最后一个节点,然后再向前走n步就能进行删除了。但是要注意的是我们这里是单向链表,不能向前走,所以我们只能考虑向后走的方法

假设链表长度是size,那么倒数第1个数就是正数第size个数,倒数第2个数就是正数第(size - 1)个数,以此类推,倒数第n个数就是正数第(size -(n-1))个数。明确这个思路就可以进行删除操作了。

我们首先要统计链表的长度是多少,所以需要一个fast指针来遍历链表,记录链表的长度。然后我们再让另一个指针slow走到n-1个节点的位置上,根据上面推导出来的公式,倒数第n个数就是正数第(size - n )个数。想要从cur节点走到第(size - n )个节点的话,那么步数step = size - n - 1。

明确上面的难点以后代码就好写了,具体代码如下

    public ListNode removeNthFromEnd(ListNode head, int n) {if(head == null){return null;}ListNode Dhead = new ListNode();Dhead.next = head;ListNode fast = Dhead;ListNode slow = Dhead;int len = 0;while(fast != null){fast = fast.next;len++;}int step = len - n - 1;while(step-- > 0){slow = slow.next;}slow.next = slow.next.next;return Dhead.next;}

面试题 02.07. 链表相交

本题的思路也是使用双指针的思路,假如说我有两个链表(此时不相交),使用两个指针同时指向两个链表的头节点,那么一起走n步,两个指针指向的下标是一样的。

顺着这个思路,假如说两个链表相交,那么我只要让两个指针指向的下标与相交节点的距离相同,然后一起向后走,那么当两个指针指向同一个节点的时候,就能完成本题的要求了。

通过不同的示例我们可以发现,两个链表相交前的长度是不一样的,那么我们为了让他们的起始下标一致,可以让长的链表走n步,其中这个n步就对应着两个链表长度的差值,这样就可以让两个指针指向的下标与相交节点的距离相同了!

最后贴上代码

public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {ListNode curA = headA;ListNode curB = headB;int stepA = 0;int stepB = 0;while(curA != null){curA = curA.next;++stepA;}curA = headA;while(curB != null){curB = curB.next;++stepB;}curB = headB;int step = Math.abs(stepA - stepB);if(stepA > stepB){while(step-- != 0){curA = curA.next;}}else if(stepA < stepB){while(step-- != 0){curB = curB.next;}}while(curA != null && curB != null && curA != curB){curA = curA.next;curB = curB.next;}return curA;}
}

142. 环形链表 II

这道题的解题思路分两个步骤,首先确认链表是否有环,其次确认环的入口节点在哪

我们首先解决第一个问题“确认链表是否有环” 

对于这个问题,我们使用双指针的方式来解决这个问题,我们让慢指针每次都走一步来遍历链表,让快指针每次走两步来遍历链表。如果链表有环,那么两者一定能相遇,因为如果有环,当慢指针刚刚进入环内,快指针已经转了n(n >= 1)圈了。以慢指针为参考系,慢指针不动,快指针相对自己在圈内每次前进一步,那么最后一定是可以相遇的!

为什么不能让快指针每次走三步,四步或者更多步?还是回到参考系这个问题上,以慢指针为参考系,慢指针不动,快指针相对自己在圈内每次前进一步,那么最后一定是可以相遇的!但是快指针相对自己在圈内每次前进两步,三步,那么很有可能快指针每次移动都越过慢指针,为了确保一定能相遇我们使用快指针相对前进一步的方式进行移动

回到第二个问题。确认了链表内有环,该如何确认入口的位置呢?

我们首先要知道的是,在慢指针走过的第一圈里面就可以遇到快指针

我们可以画一个图来证明

我们推到快指针和慢指针相遇的路程的时候可以有以下假设:

头节点到入口节点的位置距离为 x

入口节点到两个节点相遇的位置距离为 y

两个节点相遇的位置到入口的位置距离为 z

那么开始下面的数学推导

快指针走过的距离 s1 = x + y + n*(y + z) 

慢指针走过的距离 s2 = x + y

时间相同,快指针的速度是慢指针的两倍

所以得到 v1 = s1 / t = 2*v2 = s2 / t

即 x = (n-1)*(y+z) + z

也就说当我们设置两个指针,一个指向头节点,一个指向相遇处,那么两者是一定可以相遇,相遇的地方就是我们的入口处!

结束推导

开始写代码

public class Solution {public ListNode detectCycle(ListNode head) {if(head == null || head.next == null){return null;}ListNode slow = head;ListNode fast = head;while(fast != null && fast.next != null){fast = fast.next.next;slow = slow.next;if(slow == fast){slow = head;while(slow != fast){slow = slow.next;fast = fast.next;}return slow;}}if(fast == null || fast.next == null){fast = null;}return fast;}
}

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

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

相关文章

2023年第三届工业自动化、机器人与控制工程国际会议 | IET独立出版 | EI检索

会议简介 Brief Introduction 2023年第三届工业自动化、机器人与控制工程国际会议&#xff08;IARCE 2023&#xff09; 会议时间&#xff1a;2023年10月27 -30日 召开地点&#xff1a;中国成都 大会官网&#xff1a;www.iarce.org 2023年第三届工业自动化、机器人与控制工程国际…

java泛型和通配符的使用

泛型机制 本质是参数化类型(与方法的形式参数比较&#xff0c;方法是参数化对象)。 优势:将类型检查由运行期提前到编译期。减少了很多错误。 泛型是jdk5.0的新特性。 集合中使用泛型 总结&#xff1a; ① 集合接口或集合类在jdk5.0时都修改为带泛型的结构② 在实例化集合类时…

2023河南萌新联赛第(五)场:郑州轻工业大学--买爱心气球

题目链接&#xff1a;A-买爱心气球_2023河南萌新联赛第&#xff08;五&#xff09;场&#xff1a;郑州轻工业大学 (nowcoder.com) 题目描述 Alice 和 Bob 是一对竞技编程选手&#xff0c;他们路过了一家气球店&#xff0c;发现有 m 个大爱心气球和 n 个小爱心气球。他们决定玩…

SSM个人博客项目

文章目录 SSM个人博客系统实现项目介绍 一、准备工作0. 创建项目添加对应依赖1. 数据库设计2. 定时实体类 二、功能实现1.统一功能处理统一返回格式统一异常处理定义登录拦截器 2. 注册登录实现生成获取验证码密码加盐实现注册功能登录功能注销功能 3.登录用户博客列表获取登录…

clickhouse断电重启故障解决方案

业务场景 公司的一个日志系统用到了clickhouse。一线运维反映说有个生产环境因为异常断电造成服务器重启。在执行日志系统的启动脚本时&#xff0c;一直报clickhouse启动不起来&#xff0c;日志系统无法使用。 问题排查 通过阅读启动脚本代码&#xff0c;以及启动日志系统&a…

Android 项目导入高德SDK初次上手

文章目录 一、前置知识&#xff1a;二、学习目标三、学习资料四、操作过程1、创建空项目2、高德 SDK 环境接入2.1 获取高德 key2.2下载 SDK 并导入2.2.1、下载SDK 文件2.2.2、SDK 导入项目2.2.3、清单文件配置2.2.4、隐私权限 3、显示地图 一、前置知识&#xff1a; 1、Java 基…

关于在c++中使用数组名作为函数参数,或者使用数组名的地址作为函数参数问题的一些研究

前言 使用数组名作为函数参数&#xff0c;或者使用数组名的地址作为函数参数&#xff0c;常常出现于对于字符串的读入问题之中。 常有以下两种写法&#xff1a; 这是使用数组名作为函数参数 #include<cstdio> char s[100]; int main() {scanf("%s",s); }在…

【如何构建自己的基于Arduino的Scara 机器人】

【如何构建自己的基于Arduino的Scara 机器人】 1. 概述2. Scara机器人3D模型3. 3D打印机器人零件4. 组装机器人5. SCARA机器人电路图6. 完成装配7. SCARA机器人的工作原理8. 对 SCARA 机器人进行编程 – Arduino 和处理代码9. 总结在本教程中,我们将学习如何构建基于 Arduino …

导出LLaMA ChatGlm2等LLM模型为onnx

通过onnx模型可以在支持onnx推理的推理引擎上进行推理&#xff0c;从而可以将LLM部署在更加广泛的平台上面。此外还可以具有避免pytorch依赖&#xff0c;获得更好的性能等优势。 这篇博客&#xff08;大模型LLaMa及周边项目&#xff08;二&#xff09; - 知乎&#xff09;进行…

leetcode 399-除法求值

法一&#xff1a;并查集 分析示例1&#xff1a; a / b 2.0 a/ b 2.0 a/b2.0&#xff0c;说明 a 2 b a2b a2b&#xff0c; a a a和 b b b在同一个集合中 b / c 3.0 b/c3.0 b/c3.0&#xff0c;说明 b 3 c b3c b3c&#xff0c; b b b和 c c c在同一个集合中 求 a / c a/…

微服务——ES实现自动补全

效果展示 在搜索框根据拼音首字母进行提示 拼音分词器 和IK中文分词器一样的用法&#xff0c;按照下面的顺序执行。 # 进入容器内部 docker exec -it elasticsearch /bin/bash# 在线下载并安装 ./bin/elasticsearch-plugin install https://github.com/medcl/elasticsearch…

【C++】红黑树的原理与实现

文章目录 一、引言 二、红黑树的概念与性质 2、1 红黑树的概念 2、2 红黑树的性质 三、红黑树的定义与实现 3、1 红黑树的定义 3、2 插入新节点 3、2、1 默认插入红色节点 3、3 插入情况分类 3、3、1 情况一&#xff08;根据颜色向上调整&#xff09; 3、3、2 情况二&#xff0…

AIGC技术到底是什么?为什么这么火热?

AIGC技术到底是什么&#xff1f;为什么这么火热&#xff1f; ALCG技术到底是什么&#xff1f;AIGC技术的发展史AIGC技术特点AIGC技术主要用途ALGC技术未来发展 ALCG技术到底是什么&#xff1f; AIGC&#xff08;Artificial Intelligence in Game Creation&#xff09;技术是指…

OpenLayers实战,OpenLayers实现气象台风飓风运动轨迹运动动画,可调台风旋转速度和运动速度,静态图片旋转动画

专栏目录: OpenLayers实战进阶专栏目录 前言 本章使用OpenLayers实现气象中常用的台风或者飓风运动轨迹动画,支持调整台风图标旋转速度和运动速度。 不同的台风可以设置不同的运动速度和旋转速度,也可以通过变量控制图片不旋转。 本章图片使用静态png图片,并非gif动态图。…

中间件多版本冲突的4种解决方案和我们的选择

背景 在小小的公司里面&#xff0c;挖呀挖呀挖。最近又挖到坑里去了。一个稳定运行多年的应用&#xff0c;需要在里面支持多个版本的中间件客户端&#xff1b;而多个版本的客户端在一个应用里运行时会有同名类冲突的矛盾。在经过询问chatGPT&#xff0c;百度&#xff0c;googl…

在Python中定义Main函数

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 许多编程语言都有一个特殊的函数&#xff0c;当操作系统开始运行程序时会自动执行该函数。 这个函数通常被命名为main()&#xff0c;并且依据语言标准具有特定的返回类型和参数。 另一方面&#xff0c;Python解释器从文件…

SQL-每日一题【1179. 重新格式化部门表】

题目 部门表 Department&#xff1a; 编写一个 SQL 查询来重新格式化表&#xff0c;使得新的表中有一个部门 id 列和一些对应 每个月 的收入&#xff08;revenue&#xff09;列。 查询结果格式如下面的示例所示&#xff1a; 解题思路 1.题目要求我们重新格式化表&#xff0c;…

Sentieon | 应用教程: 关于读段组的建议

介绍 本文档描述了使用Sentieon Genomics软件时&#xff0c;推荐使用RGID字段以最小化潜在问题的用法。 本文档能帮助您确定设置所使用的bam文件中RG标签的不同字段的最佳实践方法。 RG字段及其用法的详细描述 RG字段的详细描述 SAM格式规范http://samtools.github.io/hts-…

Android Studio实现刮刮卡效果

代码和刮刮乐图片参考网络 实现效果 MainActivity import android.app.Activity; import android.os.Bundle;public class MainActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentV…

教雅川学缠论06-中枢

本系列文章之前讲的内容都只有上升和下降两类趋势&#xff0c;并没有提及盘整&#xff0c;在缠论中&#xff0c;中枢这个新词汇用来定义盘整&#xff0c;中枢&#xff1a; 1.至少由5条线段&#xff08;或笔&#xff09;组成 2.中枢是有方向的&#xff0c;中枢左右两侧外面的线&…