当前位置: 首页 > news >正文

代码随想录_链表

代码随想录02

链表

203.移除链表元素

力扣题目链接(opens new window)

题意:删除链表中等于给定值 val 的所有节点。

示例 1: 输入:head = [1,2,6,3,4,5,6], val = 6 输出:[1,2,3,4,5]

示例 2: 输入:head = [], val = 1 输出:[]

示例 3: 输入:head = [7,7,7,7], val = 7 输出:[]


思路

  • 先判断头结点,再进行删除
  • 设置一个虚拟头结点,一并删除,返回虚拟头结点的下一个节点(新的头结点)

代码

  • 法一:
class Solution {public ListNode removeElements(ListNode head, int val) {while(head != null && head.val == val) {head = head.next;}ListNode cur = head;while(cur != null && cur.next != null) {if(cur.next.val == val) {cur.next = cur.next.next;}else {cur = cur.next;}}return head;}
}
  • 法二:
class Solution {public ListNode removeElements(ListNode head, int val) {ListNode dummy = new ListNode();dummy.next = head;ListNode cur = dummy;while(cur != null && cur.next != null) {if(cur.next.val == val) {cur.next = cur.next.next;}else {cur = cur.next;}}return dummy.next;}
}

707.设计链表

707. 设计链表

  1. 单链表
  • 设置虚拟头结点
  • 增减操作要更新size
class MyLinkedList {class ListNode{int val;ListNode next;ListNode(int val) {this.val = val;}}private int size;private ListNode head;public MyLinkedList() {// head.next下标为0size = 0;head = new ListNode(0);}public int get(int index) {if(index < 0 || index >= size) return -1;ListNode cur = head;for(int i = 0;i <= index;i++) { cur = cur.next;}return cur.val;}public void addAtHead(int val) {ListNode node = new ListNode(val);node.next = head.next;head.next = node;size++;}public void addAtTail(int val) {ListNode cur = head;while(cur.next != null) {cur = cur.next;}cur.next = new ListNode(val);size++;}public void addAtIndex(int index, int val) {if(index < 0 || index > size) return;ListNode cur = head;for(int i = 0;i < index;i++) {// 找到index - 1cur = cur.next;}ListNode newNode = new ListNode(val);newNode.next = cur.next;cur.next = newNode;size++;}public void deleteAtIndex(int index) {if(index < 0 || index >= size) return;ListNode pre = head;for(int i = 0;i < index;i++) {// 找到index - 1pre = pre.next;// pre更新到index为i的位置, i:0 ~ index - 1}pre.next = pre.next.next;size--;}
}
  1. 双链表
class MyLinkedList {class ListNode{int val;ListNode pre,next;ListNode(int val) {this.val = val;}}int size;ListNode head,tail;public MyLinkedList() {size = 0;head = new ListNode(0);tail = new ListNode(0);head.next = tail;tail.pre = head;}public int get(int index) {if(index < 0 || index >= size) return -1;ListNode cur = head;if(index >= size/2) {// 从后往前cur = tail;for(int i = size - 1;i >= index;i--) {cur = cur.pre;}}else{// 从前往后for(int i = 0;i <= index;i++) {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;ListNode pre = head;for(int i = 0;i <= index - 1;i++) {pre = pre.next;}ListNode newNode = new ListNode(val);pre.next.pre = newNode;newNode.next = pre.next;newNode.pre = pre;pre.next = newNode;size++;}public void deleteAtIndex(int index) {if(index < 0 || index >= size) return;ListNode pre = head;for(int i = 0;i <= index - 1;i++) {pre = pre.next;}pre.next.next.pre = pre;pre.next = pre.next.next;size--;}
}

206.反转链表

206. 反转链表

1.双指针法

class Solution {public ListNode reverseList(ListNode head) {ListNode cur = head;ListNode pre = null;while(cur != null) {// 从头遍历到尾ListNode temp = cur.next; // 保存下一个cur的位置,修改cur.next指针后丢失cur.next = pre;pre = cur;// 先为pre赋值,防止cur丢失cur = temp;}return pre;}
}

2.递归法

class Solution {public ListNode reverseList(ListNode head) {return reverse(head,null);}public ListNode reverse(ListNode cur,ListNode pre) {// 1. 递归出口if(cur == null) return pre;// 2. 改变指针方向ListNode temp = cur.next;cur.next = pre;// 3. 后移return reverse(temp,cur);}
}

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

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

思路:

  1. 迭代法
class Solution {public ListNode swapPairs(ListNode head) {// 1. 初始化, 设置虚拟头结点ListNode dummyHead = new ListNode(0);dummyHead.next = head;ListNode cur = dummyHead;ListNode first,second,third;// 2. 循环, 遍历交换while(cur.next != null && cur.next.next != null) {first = cur.next;second = first.next;third = second.next;cur.next = second;second.next = first;first.next = third;// cur指向下一个要处理的结点(此时first已经被移动到second的位置了)cur = first;}// 3. 返回真正的头结点return dummyHead.next; }
}

2.递归法

class Solution {public ListNode swapPairs(ListNode head) {// 1. base case 要交换的两个不能交换, 返回首节点(上一次循环的第三个结点)if(head == null || head.next == null) return head;// 2. 先往后递归, 从后往前交换ListNode next = head.next;head.next = swapPairs(next.next);// 第一个的下一个是第三个next.next = head;// 第二个的下一个是第一个// 3. 返回头结点(上一次循环中的第三个结点)return next;}
}

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

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

  • 定义fast指针和slow指针,初始值为虚拟头结点,如图:

  • fast首先走n + 1步 ,为什么是n+1呢,因为只有这样同时移动的时候slow才能指向删除节点的上一个节点(方便做删除操作),如图:
  • fast和slow同时移动,直到fast指向末尾,如图: //图片中有错别词:应该将“只到”改为“直到”
  • 删除slow指向的下一个节点,如图:
class Solution {public ListNode removeNthFromEnd(ListNode head, int n) {// 1. dummyHead,f,s初始化ListNode dummyHead = new ListNode(0);dummyHead.next = head;ListNode f = dummyHead,s = dummyHead;// 2. f比s多走n+1步n++;while(n-- != 0 && f != null) {f = f.next;}// 3. f s 同时走while(f != null) {f = f.next;s = s.next;}// 4. 删除s.next = s.next.next;// 5. 返回return dummyHead.next;}
}
  • 时间复杂度: O(n)
  • 空间复杂度: O(1)

面试题 02.07. 链表相交

面试题 02.07. 链表相交

思路:

简单来说,就是求两个链表交点节点的指针。 这里同学们要注意,交点不是数值相等,而是指针相等。

为了方便举例,假设节点元素数值相等,则节点指针相等。

看如下两个链表,目前curA指向链表A的头结点,curB指向链表B的头结点:

此时我们就可以比较curA和curB是否相同,如果不相同,同时向后移动curA和curB,如果遇到curA == curB,则找到交点。

否则循环退出返回空指针。

法一: 先行移动长链表实现同步移动

public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {// 1. 初始化, 记录ab的长度和头结点int lenA = 0,lenB = 0;ListNode curA = headA,curB = headB;// 2. 计算两链表长度, 让A记录最长的那个while(curA != null) {lenA++;curA = curA.next;}while(curB != null) {lenB++;curB = curB.next;}curA = headA;curB = headB;if(lenB > lenA) {int t = lenB;lenB = lenA;lenA = t;ListNode tn = curB;curB = curA;curA = tn;}// 3.让A与B的尾结点对齐while(lenA != lenB) {curA = curA.next;lenA--;}// 4. 遍历, 找到相同的结点, 返回while(curA != null) {// 不能用curA != curB 因为两者会同时为nullif(curA == curB) return curA;curA = curA.next;curB = curB.next;}return null;}
}
  • 时间复杂度:O(n + m)
  • 空间复杂度:O(1)

法二: 合并链表实现同步移动

思路:
设「第一个公共节点」为 node ,「链表 headA」的节点数量为 a ,「链表 headB」的节点数量为 b ,「两链表的公共尾部」的节点数量为 c ,则有:

头节点 headA 到 node 前,共有 a−c 个节点;
头节点 headB 到 node 前,共有 b−c 个节点;

考虑构建两个节点指针 A , B 分别指向两链表头节点 headA , headB ,做如下操作:

指针 A 先遍历完链表 headA ,再开始遍历链表 headB ,当走到 node 时,共走步数为:
a+(b−c)
指针 B 先遍历完链表 headB ,再开始遍历链表 headA ,当走到 node 时,共走步数为:
b+(a−c)
如下式所示,此时指针 A , B 重合,并有两种情况:

a+(b−c)=b+(a−c)
若两链表 有 公共尾部 (即 c>0 ) :指针 A , B 同时指向「第一个公共节点」node 。
若两链表 无 公共尾部 (即 c=0 ) :指针 A , B 同时指向 null 。
因此返回 A 即可。

public class Solution {public ListNode getIntersectionNode(ListNode headA, ListNode headB) {// 1. 初始化ListNode curA = headA;ListNode curB = headB;// 2. 遍历while(curA != curB) {curA = curA != null ? curA.next : headB;curB = curB != null ? curB.next : headA;}// 3. 返回return curA;}
}
  • 时间复杂度:O(n + m)
  • 空间复杂度:O(1)

142.环形链表 II

142. 环形链表 II

思路:

  • 判断链表是否环
    • 使用快慢指针法,分别定义 fast 和 slow 指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。且相遇位置就在环内.
  • 如果有环,如何找到这个环的入口
    • 从头结点出发一个指针,从相遇节点 也出发一个指针,这两个指针每次只走一个节点, 那么当这两个指针相遇的时候就是 环形入口的节点。

代码:

public class Solution {public ListNode detectCycle(ListNode head) {// 1. 初始化快慢结点ListNode fast = head,slow = head;// 2. 移动快慢指针, Vf = 2*Vs, 找环(相遇的地方)while(fast != null && fast.next != null) {fast = fast.next.next;slow = slow.next;if(fast == slow) {// 3. 找到环后, 开始找入环的第一个结点ListNode node = head;while(node != fast) {fast = fast.next;node = node.next;}// 4. 相遇结点即为所求, 返回return fast;}}// 没有找到return null;}
}

相关文章:

代码随想录_链表

代码随想录02 链表 203.移除链表元素 力扣题目链接(opens new window) 题意&#xff1a;删除链表中等于给定值 val 的所有节点。 示例 1&#xff1a; 输入&#xff1a;head [1,2,6,3,4,5,6], val 6 输出&#xff1a;[1,2,3,4,5] 示例 2&#xff1a; 输入&#xff1a;he…...

EF Code 并发控制

【悲观控制】 不推荐用&#xff0c;EF Core 没有封装悲观并发控制的使用&#xff0c;需要使用原生Sql来使用悲观并发控制 一般使用行锁、表锁等排他锁对资源进行锁定&#xff0c;同时只有一个使用者操作被锁定的资源 拿sql server举例&#xff0c;可以使用表所、或者行所解决…...

ceph fs status 输出详解

ceph fs status 命令用于显示 Ceph 文件系统的状态信息&#xff0c;其中各列的含义如下&#xff1a; RANK&#xff1a;元数据服务器&#xff08;MDS&#xff09;的等级或标识符。 STATE&#xff1a;MDS 的当前状态&#xff0c;例如 active&#xff08;活跃&#xff09;、stan…...

FFmpeg Muxer HLS

使用FFmpeg命令来研究它对HLS协议的支持程度是最好的方法&#xff1a; ffmpeg -h muxerhls Muxer HLS Muxer hls [Apple HTTP Live Streaming]:Common extensions: m3u8.Default video codec: h264.Default audio codec: aac.Default subtitle codec: webvtt. 这里面告诉我…...

如何用SQL语句来查询表或索引的行存/列存存储方式|OceanBase 用户问题集锦

一、问题背景 自OceanBase 4.3.0版本起&#xff0c;支持了列存引擎&#xff0c;允许表和索引以行存、纯列存或行列冗余的形式创建&#xff0c;且这些存储方式可以自由组合。除了使用 show create table命令来查看表和索引的存储类型外&#xff0c;也有用户询问如何通过SQL语句…...

回归预测 | MATLAB实GRU多输入单输出回归预测

回归预测 | MATLAB实GRU多输入单输出回归预测 目录 回归预测 | MATLAB实GRU多输入单输出回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 回归预测 | MATLAB实GRU多输入单输出回归预测。使用GRU作为RNN的一种变体来处理时间序列数据。GRU相比传统的RNN有较好的记…...

【OpenGL/Assimp】渲染模型、半透明材质与封装光源

文章目录 渲染成果Assimp库准备&#xff1a;Mesh类修改&#xff1a;透明贴图使用&#xff1a;光源封装&#xff1a;使用方式在如下测试环境中&#xff1a; 渲染成果 Assimp库准备&#xff1a; 从GitHub拉取源码&#xff0c;根据网络教程&#xff0c;借助CMake生成VS工程项目&a…...

pandas与sql对应关系【帮助sql使用者快速上手pandas】

本页旨在提供一些如何使用pandas执行各种SQL操作的示例&#xff0c;来帮助SQL使用者快速上手使用pandas。 目录 SQL语法一、选择SELECT1、选择2、添加计算列 二、连接JOIN ON1、内连接2、左外连接3、右外连接4、全外连接 三、过滤WHERE1、AND2、OR3、IS NULL4、IS NOT NULL5、B…...

Linux WEB漏洞

定义&#xff1a;Linux Web 漏洞是指在基于 Linux 操作系统的 Web 应用程序、Web 服务器软件或者相关的网络服务配置中存在的安全弱点。这些漏洞可能导致攻击者未经授权访问敏感信息、篡改网页内容、执行恶意代码&#xff0c;甚至完全控制服务器。 常见类型及原理 SQL 注入漏…...

音视频入门基础:RTP专题(2)——使用FFmpeg命令生成RTP流

通过FFmpeg命令可以将一个媒体文件转推RTP&#xff1a; ffmpeg -re -stream_loop -1 -i input.mp4 -c:v copy -an -f rtp rtp://192.168.0.102:5400 但是通过ffplay尝试播放上述产生的RTP流时会报错&#xff1a;“Unable to receive RTP payload type 96 without an SDP file …...

大语言模型预训练、微调、RLHF

转发&#xff0c;如有侵权&#xff0c;请联系删除&#xff1a; 1.【LLM】3&#xff1a;从零开始训练大语言模型&#xff08;预训练、微调、RLHF&#xff09; 2.老婆饼里没有老婆&#xff0c;RLHF里也没有真正的RL 3.【大模型微调】一文掌握7种大模型微调的方法 4.基于 Qwen2.…...

vue3后台系统动态路由实现

动态路由的流程&#xff1a;用户登录之后拿到用户信息和token&#xff0c;再去请求后端给的动态路由表&#xff0c;前端处理路由格式为vue路由格式。 1&#xff09;拿到用户信息里面的角色之后再去请求路由表&#xff0c;返回的路由为tree格式 后端返回路由如下&#xff1a; …...

解决idea中无法拖动tab标签页的问题

1、按 Ctrl Alt S 打开设置&#xff0c;找到路径 File | Settings | Appearance & Behavior | Appearance 2、去掉勾选 Drag-and-drop with Alt pressed only 即可...

WMS仓库管理系统,Vue前端开发,Java后端技术源码(源码学习)

一、项目背景和建设目标 随着企业业务的不断扩展&#xff0c;仓库管理成为影响生产效率、成本控制及客户满意度的重要环节。为了提升仓库作业的透明度、准确性和效率&#xff0c;本方案旨在构建一套全面、高效、易用的仓库管理系统&#xff08;WMS&#xff09;。该系统将涵盖库…...

25/1/12 嵌入式笔记 学习esp32

了解了一下位选线和段选线的知识&#xff1a; 位选线&#xff1a; 作用&#xff1a;用于选择数码管的某一位&#xff0c;例如4位数码管的第1位&#xff0c;第2位&#xff09; 通过控制位选线的电平&#xff08;高低电平&#xff09;&#xff0c;决定当前哪一位数码管处于激活状…...

【NLP】ELMO、GPT、BERT、BART模型解读及对比分析

文章目录 一、基础知识1.1 Word Embedding&#xff08;词嵌入&#xff09;1.2 词嵌入模型1.3 神经网络语言模型NNLM 二、ELMO2.1 ELMO的提出2.2 ELMO核心思想2.3 ELMO的优缺点 三、GPT3.1 Transformer3.2 GPT简介3.3 GPT模型架构3.4 预训练及微调3.5 GPT和ELMO对比 四、BERT4.1…...

go语言学习(数组,切片,字符串)

字符串 如果里面存储的是汉字,那么其实就是存储的是UTF--8编码,所以一个字会对应多个字节.如果想要获取汉字的个数,可以使用rune,来处理unicode字符 length: utf8.RuneCountInString( s) 如果只使用len()获取的是字节的个数, 字符串的功能 1,获取字节长度 len(xx) 2,获取字…...

PM 实战 - 智能药盒PRD + 市场规模分析

写在前面 智能硬件 PRD 实例资源很少&#xff0c;Po下个人作品&#xff0c;假定前提为to Boss需求&#xff0c;目标在于覆盖产品设计核心部分&#xff08;用户画像Persona、产品逻辑图、产品架构图、软件原型图、硬件低保真设计、用例Use Case、硬件标准&#xff09;。不是申请…...

SQL刷题快速入门(二)

其他章节&#xff1a;SQL刷题快速入门&#xff08;一&#xff09; 承接上一章节&#xff0c;本章主要讲SQL的运算符、聚合函数、SQL保留小数的几种方式三个部分 运算符 SQL 支持多种运算符&#xff0c;用于执行各种操作&#xff0c;如算术运算、比较、赋值、逻辑运算等。以下…...

hive迁移后修复分区慢,怎么办?

我有1个30TB的分区表&#xff0c;客户给的带宽只有600MB&#xff0c;按照150%的耗时来算&#xff0c;大概要迁移17小时。 使用hive自带的修复分区命令&#xff08;一般修复分区比迁移时间长一点&#xff09;&#xff0c;可能要花24小时。于是打算用前面黄大佬的牛B方案。 Hive增…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

java调用dll出现unsatisfiedLinkError以及JNA和JNI的区别

UnsatisfiedLinkError 在对接硬件设备中&#xff0c;我们会遇到使用 java 调用 dll文件 的情况&#xff0c;此时大概率出现UnsatisfiedLinkError链接错误&#xff0c;原因可能有如下几种 类名错误包名错误方法名参数错误使用 JNI 协议调用&#xff0c;结果 dll 未实现 JNI 协…...

理解 MCP 工作流:使用 Ollama 和 LangChain 构建本地 MCP 客户端

&#x1f31f; 什么是 MCP&#xff1f; 模型控制协议 (MCP) 是一种创新的协议&#xff0c;旨在无缝连接 AI 模型与应用程序。 MCP 是一个开源协议&#xff0c;它标准化了我们的 LLM 应用程序连接所需工具和数据源并与之协作的方式。 可以把它想象成你的 AI 模型 和想要使用它…...

高频面试之3Zookeeper

高频面试之3Zookeeper 文章目录 高频面试之3Zookeeper3.1 常用命令3.2 选举机制3.3 Zookeeper符合法则中哪两个&#xff1f;3.4 Zookeeper脑裂3.5 Zookeeper用来干嘛了 3.1 常用命令 ls、get、create、delete、deleteall3.2 选举机制 半数机制&#xff08;过半机制&#xff0…...

用docker来安装部署freeswitch记录

今天刚才测试一个callcenter的项目&#xff0c;所以尝试安装freeswitch 1、使用轩辕镜像 - 中国开发者首选的专业 Docker 镜像加速服务平台 编辑下面/etc/docker/daemon.json文件为 {"registry-mirrors": ["https://docker.xuanyuan.me"] }同时可以进入轩…...

mac 安装homebrew (nvm 及git)

mac 安装nvm 及git 万恶之源 mac 安装这些东西离不开Xcode。及homebrew 一、先说安装git步骤 通用&#xff1a; 方法一&#xff1a;使用 Homebrew 安装 Git&#xff08;推荐&#xff09; 步骤如下&#xff1a;打开终端&#xff08;Terminal.app&#xff09; 1.安装 Homebrew…...

PHP 8.5 即将发布:管道操作符、强力调试

前不久&#xff0c;PHP宣布了即将在 2025 年 11 月 20 日 正式发布的 PHP 8.5&#xff01;作为 PHP 语言的又一次重要迭代&#xff0c;PHP 8.5 承诺带来一系列旨在提升代码可读性、健壮性以及开发者效率的改进。而更令人兴奋的是&#xff0c;借助强大的本地开发环境 ServBay&am…...

【从零开始学习JVM | 第四篇】类加载器和双亲委派机制(高频面试题)

前言&#xff1a; 双亲委派机制对于面试这块来说非常重要&#xff0c;在实际开发中也是经常遇见需要打破双亲委派的需求&#xff0c;今天我们一起来探索一下什么是双亲委派机制&#xff0c;在此之前我们先介绍一下类的加载器。 目录 ​编辑 前言&#xff1a; 类加载器 1. …...

破解路内监管盲区:免布线低位视频桩重塑停车管理新标准

城市路内停车管理常因行道树遮挡、高位设备盲区等问题&#xff0c;导致车牌识别率低、逃费率高&#xff0c;传统模式在复杂路段束手无策。免布线低位视频桩凭借超低视角部署与智能算法&#xff0c;正成为破局关键。该设备安装于车位侧方0.5-0.7米高度&#xff0c;直接规避树枝遮…...