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

【链表】一文搞定链表算法:从基础到实战

提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 例题
    • 一、两数相加
    • 二、两两交换链表中的节点
    • 三、重排链表
    • 四、合并K个升序链表
    • 五、 K个⼀组翻转链表
  • 结语


在这里插入图片描述

前言

什么是链表算法:

链表算法,是围绕链表数据结构构建的一系列操作方法。链表由一个个节点组成,节点间靠指针相连,内存存储不连续。链表算法涵盖诸多方面,像创建链表,按特定逻辑将节点串联起来;插入节点,能灵活添加新数据;删除节点,可移除指定元素。遍历链表能逐个访问数据,查找则用于定位特定值。此外,还有链表反转、合并等复杂操作。在实际应用中,链表算法在操作系统任务调度、数据库索引管理等方面发挥关键作用,为高效处理动态数据提供有力支持 。

下面,本篇文章将通过以下几个例题详细介绍阐述链表算法相关知识!

例题

一、两数相加

  1. 题目链接:两数相加
  2. 题目描述:

给你两个 ⾮空 的链表,表⽰两个⾮负的整数。它们每位数字都是按照 逆序 的⽅式存储的,并且每个 节点只能存储 ⼀位 数字。 请你将两个数相加,并以相同形式返回⼀个表⽰和的链表。 你可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例1:
在这里插入图片描述
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.
示例 2:
输入:l1 = [0], l2 = [0]
输出:[0]
⽰例 3:
输⼊:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]
提示: 每个链表中的节点数在范围 [1, 100] 内 0 <= Node.val <= 9 题目数据保证列表表示的数字不含前导零

  1. 解法(模拟):
    两个链表都是逆序存储数字的,即两个链表的个位数、⼗位数等都已经对应,可以直接相加。 在相加过程中,我们要注意是否产⽣进位,产⽣进位时需要将进位和链表数字⼀同相加。如果产⽣进位的位置在链表尾部,即答案位数⽐原链表位数⻓⼀位,还需要再 new ⼀个结点储存最⾼位。
  2. 代码示例:
   public ListNode addTwoNumbers(ListNode l1, ListNode l2) {ListNode newHead = new ListNode(0);ListNode prev = newHead;int t = 0;while (l1 != null || l2 != null || t != 0) {if (l1 != null) {t += l1.val;l1 = l1.next;}if (l2 != null) {t += l2.val;l2 = l2.next;}prev.next = new ListNode(t % 10);prev = prev.next;t /= 10;}return newHead.next;}

二、两两交换链表中的节点

  1. 题目链接:两两交换链表中的节点
  2. 题目描述:

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

  1. 解法(模拟):
    算法思路:通过画图模拟算法!

  2. 代码示例:

  public ListNode swapPairs(ListNode head) {if (head == null || head.next == null) {return head;}ListNode newHead = new ListNode(0);newHead.next = head;ListNode prev = newHead, cur = prev.next, next = cur.next, nnext = next.next;while (cur != null && next != null) {prev.next = next;next.next = cur;cur.next = nnext;prev = cur;cur = nnext;if (cur != null) next = cur.next;if (next != null) nnext = next.next;}return newHead.next;}

这里,这道题仍有第二种解法:递归,本篇不重点讨论递归,仅将代码示例放于此文:

  public ListNode swapPairs(ListNode head) {if(head==null||head.next == null){return head;}ListNode newhead = swapPairs(head.next.next);ListNode ret = head.next;ret.next = head;head.next = newhead;return ret;}

三、重排链表

  1. 题目链接:重排链表
  2. 题目描述:

给定⼀个单链表 L 的头节点 head ,单链表 L 表⽰为:L(0) → L(1) → … → L(n - 1) → L(n)
请将其重新排列后变为:L(0) → L(n) → L(1) → L(n - 1) → L(2) → L(n - 2) → 不能只是单纯的改变节点内部的值,⽽是需要实际的进行节点交换。
⽰例 1:
在这里插入图片描述输⼊:head = [1,2,3,4]
输出:[1,4,2,3]
⽰例 2:
在这里插入图片描述输⼊:head = [1,2,3,4,5]
输出:[1,5,2,4,3]
提示:
• 链表的长度范围为 [1, 5 * 10(4)]
• 1 <= node.val <= 1000

  1. 解法:
    算法思路:
    找中间节点;
    中间部分往后的逆序;
    合并两个链表

  2. 代码示例:

 public void reorderList(ListNode head) {if (head == null || head.next == null || head.next.next == null) return;ListNode slow = head, fast = head;while (fast != null && fast.next != null) {slow = slow.next;fast = fast.next.next;}ListNode newHead = new ListNode(0);ListNode cur = slow.next;slow.next = null;//切断链表//头插while (cur != null) {ListNode next = cur.next;cur.next = newHead.next;newHead.next = cur;cur = next;}//合并ListNode cur1 = head, cur2 = newHead.next;ListNode ret = new ListNode(0);ListNode prev = ret;while (cur1 != null) {//先放第一个链表prev.next = cur1;prev = cur1;cur1 = cur1.next;//在合并第二个链表if (cur2 != null) {prev.next = cur2;prev = cur2;cur2 = cur2.next;}}}

四、合并K个升序链表

  1. 题目链接:合并K个升序链表
  2. 题目描述:

给你⼀个链表数组,每个链表都已经按升序排列。 请你将所有链表合并到⼀个升序链表中,返回合并后的链表。
⽰例 1: 输⼊:lists = [[1,4,5],[1,3,4],[2,6]]
输出:[1,1,2,3,4,4,5,6]
解释:链表数组如下:
[
1->4->5,
1->3->4,
2->6
]
将它们合并到⼀个有序链表中得到。
1->1->2->3->4->4->5->6
⽰例 2:
输⼊:lists = []
输出:[]
⽰例 3:
输⼊:lists = [[]]
输出:[]
提⽰: k == lists.length
0 <= k <= 10^4
0 <= lists[i].length <= 500
-10^4 <= lists[i][j] <= 10^4
lists[i] 按 升序 排列
lists[i].length 的总和不超过 10^4

  1. 解法⼀(利用堆):
    算法思路:
    合并两个有序链表是比较简单且做过的,就是⽤双指针依次比较链表 1 、链表 2 未排序的最⼩元 素,选择更小的那⼀个加⼊有序的答案链表中。 合并 K 个升序链表时,我们依旧可以选择 K 个链表中,头结点值最小的那⼀个。那么如何快速的得 到头结点最小的是哪⼀个呢?⽤堆这个数据结构就好啦~ 我们可以把所有的头结点放进⼀个⼩根堆中,这样就能快速的找到每次 K 个链表中,最小的元素是哪个。

  2. 代码示例:

 public ListNode mergeKLists(ListNode[] lists) {PriorityQueue<ListNode> heap = new PriorityQueue<>((v1, v2) -> v1.val - v2.val);// 将所有的头节点加入到小根堆中for (ListNode l : lists) {if (l != null) {heap.offer(l);}}//合并ListNode ret = new ListNode(0);ListNode prev = ret;while (!heap.isEmpty()) {ListNode t = heap.poll();prev.next = t;prev = t;if (t.next != null) heap.offer(t.next);}return ret.next;}

五、 K个⼀组翻转链表

  1. 题目链接:K个⼀组翻转链表
  2. 题目描述:

给你链表的头节点 head ,每 k 个节点⼀组进行翻转,请你返回修改后的链表。
k 是⼀个正整数,它的值⼩于或等于链表的长度。如果节点总数不是 k 的整数倍,那么请将最后剩余 的节点保持原有顺序。
你不能只是单纯的改变节点内部的值,⽽是需要实际进⾏节点交换。
⽰例 1:
在这里插入图片描述
输⼊:head = [1,2,3,4,5], k = 2
输出:[2,1,4,3,5]
⽰例 2:
在这里插入图片描述
输⼊:head = [1,2,3,4,5], k = 3 输出:[3,2,1,4,5]
提⽰: 链表中的节点数⽬为 n 1 <= k <= n <= 5000
0 <= Node.val <= 1000

  1. 解法(模拟):
    算法思路:
    本题的⽬标⾮常清晰易懂,不涉及复杂的算法,只是实现过程中需要考虑的细节比较多。 我们可以把链表按 K 个为⼀组进⾏分组,组内进⾏反转,并且记录反转后的头尾结点,使其可以和 前、后连接起来。思路⽐较简单,但是实现起来是⽐较复杂的。
    我们可以先求出⼀共需要逆序多少组(假设逆序 n 组),然后重复 n 次⻓度为 k 的链表的逆序即 可。
  2. 代码示例:
  public ListNode reverseKGroup(ListNode head, int k) {if (head == null || head.next == null) return head;int n = 0;ListNode cur = head;while (cur != null) {cur = cur.next;n++;}n /= k;ListNode newHead = new ListNode(0);ListNode prev = new ListNode(0);cur = head;for (int i = 0; i < n; i++) {ListNode tmp = cur;for (int j = 0; j < k; j++) {//头插逻辑ListNode next = cur.next;cur.next = prev.next;prev.next = cur;cur = next;}prev = tmp;}// 把后面不需要逆序的地方链接起来prev.next = cur;return newHead.next;}

结语

本文到这里就结束了,主要介绍了链表算法,并通过几道例题更加深入了解链表算法相关知识,重点在于画图理清题目思路,注重代码细节。希望能够对你有帮助!

以上就是本文全部内容,感谢各位能够看到最后,创作不易,希望大家多多支持!

最后,大家再见!祝好!我们下期见!

相关文章:

【链表】一文搞定链表算法:从基础到实战

提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言例题一、两数相加二、两两交换链表中的节点三、重排链表四、合并K个升序链表五、 K个⼀组翻转链表 结语 前言 什么是链表算法&#xff1a; 链表算法&#xff0…...

瑞萨RA系列使用JLink RTT Viewer输出调试信息

引言 还在用UART调试程序么?试试JLINK的RTT Viewer吧!不需占用UART端口、低资源暂用、实时性高延时微秒级,这么好的工具还有什么理由不用了! 目录 一、JLink RTT Viewer 简介 二、软件安装 三、工程应用 3.1 SEGGER_RTT驱动包 3.2 手搓宏定义APP_PRINT 3.3 使用APP_…...

DEFI币生态重构加速,XBIT去中心化交易所引领DEX安全新范式

2025年3月18日&#xff0c;全球加密市场在监管与技术共振下迎来结构性变革。去中心化金融&#xff08;DeFi&#xff09;代币DEFI币因跨链流动性协议升级引发社区热议&#xff0c;而币应XBIT去中心化交易所&#xff08;以下简称XBIT&#xff09;凭借其链上透明验证机制、无需下载…...

高性能缓存:使用 Redis 和本地内存缓存实战示例

在现代高并发系统中&#xff0c;缓存技术是提升性能和降低数据库压力的关键手段。无论是分布式系统中的Redis缓存&#xff0c;还是本地高效的本地内存缓存&#xff0c;合理使用都能让你的应用如虎添翼。今天&#xff0c;我们将基于go-dev-frame/sponge/pkg/cache库的代码示例&a…...

Linux动态库和静态库

Linux动态库和静态库 Linux动态库和静态库动静态库的基本原理可执行程序的生成过程动静态库的本质 认识动静态库背后的库支持动静态库的命名静态链接示例 动静态库各自的特征静态库动态库 静态库的打包与使用示例文件打包1. 生成目标文件2. 打包静态库3. 组织文件使用 Makefile…...

13 IO流:字节流、字符流、缓冲流、文件复制(字节/字符/缓冲区)、字符转换流、打印流、IO框架(黑马Java视频笔记)

文章目录 IO流 >> 读写数据的方案1. 认识IO流1&#xff09;IO流的分类2&#xff09;IO流的体系 2. 文件字节输入流2.1 创建文件字节流对象2.2 读取文件1&#xff09;使用read()方法一个一个字节的读取2&#xff09;使用字节数组读取数据:byte[]3&#xff09;使用字节流读…...

深入理解 TypeScript 中的迭代器(Iterators)与生成器(Generators)

一、为什么需要迭代协议&#xff1f; 在现代 JavaScript/TypeScript 开发中&#xff0c;我们经常需要处理各种集合型数据&#xff1a;数组、Map、Set 甚至是自定义数据结构。ES6 引入的迭代协议&#xff08;Iteration Protocols&#xff09;正是为了解决统一遍历机制的问题。通…...

靶场(十四)---小白心得思路分享---Extplorer

启程&#xff1a; 开始扫描端口服务&#xff0c;发现什么都没有&#xff0c;果断进行下一步目录扫描 PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 8.2p1 Ubuntu 4ubuntu0.5 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 3072 98:4e:5d:e1:e6:97:29:6f:…...

逆向中常见的加密算法识别

1、base64及换表 base64主要是将输入的每3字节&#xff08;共24bit&#xff09;按照每六比特分成一组&#xff0c;变成4个小于64的索引值&#xff0c;然后通过一个索引表得到4个可见的字符。 索引表为一个64字节的字符串&#xff0c;如果在代码中发现引用了这个索引表“ABCDEF…...

【初学者】怎样学习、使用与研究算法?

李升伟 整理 学习、使用与研究算法是一个系统化的过程&#xff0c;涉及理论学习、实践应用和深入研究。以下从学习方法、使用技巧和研究方向三个方面进行详细阐述&#xff1a; 一、学习方法 1. 分阶段学习 初级阶段&#xff1a;掌握经典算法&#xff0c;如最短路径算法&…...

【愚公系列】《高效使用DeepSeek》018-错题本整理

🌟【技术大咖愚公搬代码:全栈专家的成长之路,你关注的宝藏博主在这里!】🌟 📣开发者圈持续输出高质量干货的"愚公精神"践行者——全网百万开发者都在追更的顶级技术博主! 👉 江湖人称"愚公搬代码",用七年如一日的精神深耕技术领域,以"…...

Linux上的`i2c-tools`工具集的编译构建和安装

源码复制到Ubuntu系统中并解压 的i2c-tools工具集的源码百度网盘下载链接&#xff1a; https://pan.baidu.com/s/1XNuMuT1auT1dMzYo3LAFmw?pwdi6xe 终端进入源码目录 cd /home/book/mybuild/i2c-tools-4.2执行编译构建命令 运行下面的命令进行编译构建 make CC${CROSS_COM…...

langgraph简单Demo(使用langserve实现外部调用)

前言 这个示例是研究如何使用langserve实现外部调用 接入大模型参考文章&#xff1a;接入阿里云百炼 1、安装依赖 pip install langserve fastapi uvicorn pip install sse_starlette 2、代码实现 from fastapi import FastAPI from langchain_core.messages import HumanM…...

【C#高阶编程】—单例模式详解

C# 单例模式 单例模式是一种设计模式&#xff0c;用于确保一个类只有一个实例&#xff0c;并提供一个全局访问点来访问该实例。单例模式常用于需要全局唯一对象的场景&#xff0c;比如配置文件管理、日志记录、数据库连接池等。 单例模式的核心特点 私有构造函数&#xff1a;…...

折叠树报表

折叠树报表中包含了三种信息: 1.树组织信息-可展开、收拢 2.节点的统计信息(汇总求和) 3.每个节点对应的数据信息 一、准备数据 mysql8 数据库中存在两张表 org和store表。 org表和部分数据如下,其中orgname是组织的名称,codepath是完整的组织代码,seq是每个节点的顺序,可…...

Python个人学习笔记(16):模块(os)

四、os模块 主要用于文件夹处理 &#xff08;一&#xff09;文件夹相关 os.makedirs(‘dirname1/dirname2’) &#xff1a;创建文件夹目录&#xff0c;不能重复创建&#xff0c;用的多 代码&#xff1a; os.makedirs(a/b/c)结果&#xff1a; os.removedirs(‘dirname1’)&…...

虚拟地址空间(下)进程地址空间(上)

一.关于页表组成 1.权限&#xff08;rwx) 作用&#xff1a;如1.让代码区变成只读的 2.写时拷贝的实现&#xff1a;子进程创建时其页表指向的父进程代码和数据权限都是只读的&#xff0c;子进程试图修改&#xff0c;触发错误&#xff0c;系统开始写时拷贝。 来源&#xff1a;…...

【数据集分享】青藏高原两次强震玛多地震和漾濞地震的震源过程

2021年5月21日&#xff0c;5小时内在青藏高原不同区域发生了漾濞6.4级和玛多7.4级强烈地震&#xff0c;表明印度板块和欧亚大陆板块的碰撞汇聚作用下青藏高原持续和频繁的 剧烈构造运动和地震活动。本研究利用地震记录和空间对地观测同震位移资料&#xff08;InSAR&#xff09;…...

jmeter环境搭建及使用

Meter 是一个开源的性能测试工具&#xff0c;用于测试静态和动态资源的性能。 1、安装 官网下载&#xff1a; 下载地址&#xff1a;Apache JMeter - Download Apache JMeter 网盘下载&#xff1a; 通过百度网盘分享的文件&#xff1a;apache-jmeter-5.6.3.rar 链接&#x…...

Python 鼠标轨迹算法 - 防止游戏检测

一.简介 鼠标轨迹算法是一种模拟人类鼠标操作的程序&#xff0c;它能够模拟出自然而真实的鼠标移动路径。 鼠标轨迹算法的底层实现采用C/C语言&#xff0c;原因在于C/C提供了高性能的执行能力和直接访问操作系统底层资源的能力。 鼠标轨迹算法具有以下优势&#xff1a; 模拟…...

网络编程--服务器双客户端聊天

写一个服务器和客户端 运行服务器和2个客户端&#xff0c;实现聊天功能 客户端1和客户端2进行聊天&#xff0c;客户端1将聊天数据发送给服务器&#xff0c;服务器将聊天数据转发给客户端2 要求&#xff1a; 服务器使用 select 模型实现 &#xff0c;客户端1使用 poll 模型实现…...

yum软件包乾坤大挪移(Yum Package Qiankun Great Migration)

yum软件包乾坤大挪移 背景 由于很多的生产环境是无法连接外网的&#xff0c;因此用yum或者dnf命令来安装软件包常常是一个比较麻烦的事情&#xff0c;原因是很多软件的依赖很复杂&#xff0c;如果要一个个下载、拷贝、再安装&#xff0c;这往往是一个非常繁琐冗杂的过程&…...

Java:读取中文,read方法

public static void main(String[] args) throws IOException {FileReader fr new FileReader("C:\\aaa\\a.txt");//字符流的底层也是一个字节一个字节读取的&#xff0c;遇到中文就一次读多个&#xff0c;GBK一次读两个&#xff0c;UTF-8一次读三个字节//idea默认U…...

[GHCTF 2025]真会布置栈吗?

题目是一个聊天室,我们先按照题目使用 /help Help: /help 显示此帮助信息 /msg [text] 在当前频道发送消息 /nick [name] 更改你的用户名 /list 列出可用的频道 /join [channel] 切换到不同的频道 /channel …...

集合的练习1-2

//练习1&#xff1a; import java.util.ArrayList;public class ArraylistTest1 {public static void main(String[] args){ArrayList<String> listnew ArrayList<>();//需求&#xff1a;定义一个集合&#xff0c;添加字符串&#xff0c;并进行遍历//遍历格式&…...

英语词性--数词

文章目录 数词概念数词分词基数词序数词 基数与序数词的区别基变序的规律 数词概念 数词&#xff08;Numerals&#xff09; 是英语中用于表示 数量&#xff08;基数&#xff09;或顺序&#xff08;序数&#xff09; 的词类&#xff0c;通常用于描述数字、计数、顺序等。 例如&…...

面试整理--一个报告生成的方案解析

最近又快到了年后找工作的时间&#xff0c;近期写点工作积累&#xff0c;供大家参考。 欢迎关注公主号【测试开发备忘录】&#xff0c;交流职场技巧和经验 首先从工作中一个报错来展开: Start directory is not importable: 错误信息 "Start directory is not importable…...

C#零基础入门篇(18. 文件操作指南)

## 一、文件操作基础 在C#中&#xff0c;文件操作主要通过System.IO命名空间中的类来实现&#xff0c;例如File、FileStream、FileInfo等。 ## 二、常用文件操作方法 ### &#xff08;一&#xff09;文件读取 1. **使用File.ReadAllText方法读取文件内容为字符串** …...

Linux 一步部署DHCP服务

#!/bin/bash #脚本作者和日期 #author: PEI #date: 20250319 #检查root权限 if [ "$USER" ! "root" ]; then echo "错误&#xff1a;非root用户&#xff0c;权限不足&#xff01;" exit 0 fi #防火墙与高级权限 systemctl stop firewa…...

如何打造安全稳定的亚马逊采购测评自养号下单系统?

在当今的电商领域&#xff0c;亚马逊作为全球领先的在线购物平台&#xff0c;其商品种类繁多&#xff0c;用户基数庞大&#xff0c;成为了众多商家和消费者的首选。而对于一些需要进行商品测评或市场调研的用户来说&#xff0c;拥有一个稳定、安全的亚马逊账号体系显得尤为重要…...